skip to main |skip to sidebar

2007-04-29

Apollo的核心 - Shell类

Shell是连接Apollo程序和OS的对象。根据官方文档,虽然今后很有可能会变更它的方法,但还是把他的核心说一下。

因为Shell对象会在程序启动时自动生成,所以不需要在程序中创建。它是一个单例对象(Singleon),用 Shell.shell 来访问。

Shell类的属性和方法

Shell类的属性列表:

Code:
id:String                 // 程序的ID
activeWindow:NativeWindow // 现在活动的窗口
focusWindow:NativeWindow  // 现在拥有焦点的窗口
autoExit:Boolean          // 如果是true,就在关闭了所有窗口时结束程序

id是程序配置文件(程序名-app.xml)的name标签的值。id是程序的标志符,必须与其他的程序的不一样。所以推荐使用类似于"com.sample.apollo.ApplicationName"的名字。能在id里使用的字符是英数字,"."和"-"。

activeWindow是现在活动的窗口,focusWindow是现在拥有焦点的窗口。如果对象窗口不是属于Shell(不是Apollo打开的窗口)的话,会是 null

autoExit值为 true (默认值)时,就在关闭了所有窗口时结束程序; false 时必须调用Shell.shell.exit()来结束程序。但由于Alpha版的BUG,即时调用exit()也不会结束程序。所以至少在Alpha版里最好不要碰autoExit

注意,在事件里调用exit()时不会马上结束程序,而是在事件处理完了的时候结束。

Shell类的事件

Shell类的事件定义如下:

Code:
activate      // 当程序变为活动时
deactivate    // 当程序变为非活动时
invoke        // 当程序启动时
networkChange // 当网络链接发生变化时

activate是当程序变为活动时,deactivate是当程序变为非活动时触发的事件。Alpha版好像activatedeactivate事件只触发于最初打开的窗口。

Invoke是当程序启动时触发。这个事件会保存直到添加了听诊器(Listener)为止,所以可以在程序启动后处理的。

Inboke事件类型是InvokeEvent。它拥有以下2个属性:

Code:
arguments:Array // 启动时给与的参数列表
currentDirectory:File // 参数里有相对路径的基准路径(绝对路径 = 基准路径 + 相对路径)

注意,Apollo不能同时启动一个程序数次。在第2次程序启动时,会触发第1次启动的程序的Inboke事件。

最后一个networkChange事件当网络链接发生变化时触发。比如网线断开了。

我的Blog这次GooglePR升为2了!

PR又开始了大规模更新,此次PR更新从4月26号开始,据说用的是4月3日的数据。google一般更新PR值都是每3个月一次,最长的一次4个多月。上次大致更新时间为2007年1月11日。

祝贺一下,我的Blog这次升为2了,小高兴一下,呵呵……

2007-04-27

NativeWindow 类的事件详解2

displayStateChanging 的取消

NativeWindow 类的事件详解1里也提到,ing系的事件是可以取消的。比如取消 displayStateChanging 事件就意味着不变更 displayState,也就是说不进行最大化/最小化。

在AS3里,标准的取消事件方法是调用preventDefault()。如果直接使用上次的例子的话,只需要在onDispStateEvent()里加上preventDefault()。

因为onDispStateEvent()方法是displayStateChange和displayStateChanging两个事件共用了的,所以有可能events是不可取消的displayStateChange事件。所以需要判断是哪一个事件:

Code:Actionscript
private function onDispStateEvent(e:NativeWindowDisplayStateEvent):void {
  if (e.cancelable) { // 检测是否可以取消
    e.preventDefault(); // 取消事件
  }
  trace("type:", e.type, e.afterDisplayState);
}

执行后,就会发现系统窗口的按钮会没反应,但程序里的按钮却照常不误。并且如果在程序里的按钮事件里触发displayStateChanging事件的话,程序里的按钮就与系统窗口的按钮动作一样了。

NativeWindowBoundsEvent

如果NativeWindow的bounds属性被变更,就会触发NativeWindowBoundsEvent。bounds被触发的情况是窗口的大小或位置被改变时。

NativeWindowBoundsEvent拥有beforeBounds和afterBounds属性,分别指变更前和变更后的值。ing系(moving,resizing)事件的beforeBounds为当前值,完成通知(move,resize)事件的afterBounds为当前值。

与NativeWindowDisplayStateEvent一样,move和resize事件会在任何条件下触发,但moving和resizing不会在代码里触发,只会在用鼠标拖动系统窗口等条件下触发。

注意,在Stage类里也有一个resize事件,这是在画面的大小发生改变,重画时触发的。

以下是测试NativeWindowBoundsEvent的例子。

Code:MXML
<?xml version="1.0" encoding="utf-8"?>
<mx:ApolloApplication xmlns:mx="http://www.adobe.com/2006/mxml" applicationComplete="addListeners()">

  <mx:Script>
    <![CDATA[
    private function addListeners():void {
      stage.window.addEventListener( NativeWindowBoundsEvent.RESIZE, onBoundsEvent);
      stage.window.addEventListener( NativeWindowBoundsEvent.RESIZING, onBoundsEvent);
      stage.window.addEventListener( NativeWindowBoundsEvent.MOVE, onBoundsEvent);
      stage.window.addEventListener( NativeWindowBoundsEvent.MOVING, onBoundsEvent);
    }
    private function onBoundsEvent(e:NativeWindowBoundsEvent):void {
      trace("type:", e.type, e.afterBounds);
    }
    private function onBoxMouseDown(e:MouseEvent):void {
      stage.window.startResize( NativeWindowResize.BOTTOM_RIGHT);
    }
    private function onBarMouseDown(e:MouseEvent):void {
      stage.window.startMove();
    }
    ]]>
  </mx:Script>
  <mx:HBox mouseDown="onBarMouseDown(event)" width="100%" height="24" backgroundColor="#ffffff"/>
  <mx:HBox mouseDown="onBoxMouseDown(event)" width="100%" height="100%" backgroundColor="#ffffff"/>
</mx:ApolloApplication>

close与closing事件

这是关闭窗口时触发的事件。事件类型为flash.events.Event。

closing是在关闭前,close是在关闭后触发。如果取消closing事件,窗口将不会被关闭。其余与NativeWindowBoundsEvent的触发方式一样,在这里就不重复了。

(完)

2007-04-22

NativeWindow 类的事件详解1

以下是 NativeWindow 的事件列表:

Code:
displayStateChange //NativeWindow 对象的 displayState 属性被变更后
displayStateChanging //NativeWindow 对象的 displayState 属性被变更前
move //NativeWindow 对象在桌面上移动后
moving //NativeWindow 对象在桌面上移动前
resize //NativeWindow 对象改变大小后
resizing //NativeWindow 对象改变大小前
close //NativeWindow 对象被关闭后
closing //NativeWindow 对象被关闭前

我想一看就明白各2个事件成为一对。定义了对窗口的4种操作的紧接之前和完成后各自的状态的事件。

ing 结束的事件赋予像警告一样的地位,在处理事件完成前,可以确认状况,根据场合的不同取消处理等。为此 ing结束的事件全都是可以取消的。

另一方面,不以ing 结束的事件是通知完成后的事件。需要事后处理的情况使用。

下面稍微详细地查看以下各个事件。

NativeWindowDisplayStateEvent

是首先有关 displayState 属性变更的事件。displayStateChanging 是NativeWindow 对象的 displayState 被变更的紧接之前,而displayStateChange 是根据 displayState 被变更了之后的 NativeWindow 的处理(dispatch)。

这个时候dispatch的事件对象的形式为 flash.events.NativeWindowDisplayStateEvent 。这个对象的事件有着 beforeDisplayState 和 afterDisplayState 的属性,表示各自变更前的值和变更后的值。

因为在displayStateChanging 事件的情况下变更还没完成,在接收了事件的时刻的 displayState 属性的值就是 beforeDisplayState 。但在 displayStateChange 事件的情况下变更已经进行,那个时刻的 displayState 属性的值就是 afterDisplayState 。

下面来写一个例子。首先,确认程序配置文件(程序名-app.xml)的 rootContent 标签的 systemChrome 为 standard 。
Code:XML
<rootContent systemChrome="standard" transparent="false" visible="true">[SWF reference is generated]</rootContent>

下面的例子是在 applicationComplete事件里添加listener (onDispStateEvent)。在onDispStateEvent 里面 trace()输出事件信息,请用debug 方式执行。

Code: MXML
<?xml version="1.0" encoding="utf-8"?>
<mx:ApolloApplication xmlns:mx="http://www.adobe.com/2006/mxml" applicationComplete="addListeners()">
<mx:Script>
<![CDATA[
private function addListeners():void {
stage.window.addEventListener( NativeWindowDisplayStateEvent.DISPLAY_STATE_CHANGE, onDispStateEvent);
stage.window.addEventListener( NativeWindowDisplayStateEvent.DISPLAY_STATE_CHANGING, onDispStateEvent);
}

private function onDispStateEvent(e:NativeWindowDisplayStateEvent):void {
trace("type:", e.type, e.afterDisplayState);
}

private function onMinBtnClick(e:MouseEvent):void {
stage.window.minimize();
}
private function onMaxBtnClick(e:MouseEvent):void {
if (stage.window.displayState != NativeWindowDisplayState.MAXIMIZED) {

stage.window.maximize();
maxBtn.label = "v";
}else{
stage.window.restore();
maxBtn.label = "\u25A2";
}
}
private function onCloseBtnClick(e:MouseEvent):void {

stage.window.close();
}
]]>
</mx:Script>
<mx:HBox width="100%" backgroundColor="#ffffff">
<mx:Button id="minBtn" label="_" click="onMinBtnClick(event)" />
<mx:Button id="maxBtn" label='{"\u25A2"}' click="onMaxBtnClick(event)" />
<mx:Button id="closeBtn" label="X" click="onCloseBtnClick(event)" />
</mx:HBox>
<mx:HBox width="100%" height="100%" backgroundColor="#ffffff"/>
</mx:ApolloApplication>

有人可能会注意到系统chrome的最小化/最大化按钮和窗口内的最小化/最大化按钮的事件有些差异。

由系统chrome的按钮来最大化窗口会触发 displayStateChanging 和 displayStateChange 两个事件。

但如果按了窗口内的按钮来最大化窗口,displayStateChange 事件以外的不会发生。(即 ing 事件不会发生)。

这是因为由系统chrome的按钮来最大化窗口的话,他考虑到处理实际被进行之前的对应 。为此,NativeWindow 自动地做了 displayStateChanging dispatch。

但如果按窗口内的按钮来调用 minimize()等方法,处理实际被进行之前的对应应该是可以的(在minimize()等方法里写)。为此即使调用了 minimize(), maximize(), restore(), displayStateChanging 也不自动dispatch。

如果想在 minimize()等调用后,触发 displayStateChanging 事件的话,也可以追加以下语句:

Code: Actionscript
//以minimize()为例
private function onMinBtnClick(e:MouseEvent):void {
stage.window.minimize();
var dispStateEvent:NativeWindowDisplayStateEvent = new NativeWindowDisplayStateEvent(
NativeWindowDisplayStateEvent.DISPLAY_STATE_CHANGING, true, true,
stage.window.displayState, NativeWindowDisplayState.MINIMIZED);
stage.window.dispatchEvent(dispStateEvent);
}

这样,就与由系统chrome的按钮来最大化窗口是一样的了。把程序配置文件(程序名-app.xml)的 rootContent 标签的 systemChrome 变为 none 就可以看到效果了。

未完待续。

打开新的Apollo窗口的方法

要从Apollo程序打开新的窗口,需要生成NativeWindow或它的子类的实例。下面为NativeWindow的构造函数:

Code:
public function NativeWindow(visible:Boolean, initOptions:NativeWindowInitOptions)

NativeWindow的构造函数有2个参数。

第一个参数是窗口制作的时候是否显示。 制作的窗口在表示位置和大小等有可能会有修改。如果修改时窗口在表示了的状态下进行的话这些的处理的途中的阶段也会在画面上表示了。所以最好是首先将visible = false (不显示),必要的修改结束了再 让 visible = true 来显示窗口。

同样,如果不想在Apollo程序启动的时候 显示画面,可以把 程序配置文件(程序-app.xml)里的rootContent标签的visible改为false。再在修改完后再 让 visible = true 来显示窗口。

第二个参数是指定窗口初始化所使用的选项的 NativeWindowInitOptions。NativeWindowInitOptions的定义为:

Code:
systemChrome:String // 窗口使用的系统chrome的种类
transparent:Boolean // 窗口是否能够透明
resizable:Boolean // 是否能改变窗口的大小
maximizable:Boolean // 是否能最大化能窗口
minimizable:Boolean // 是否能最小化能窗口

各自的属性的初始值如下。

Code:
systemChrome = NativeWindowSystemChrome.STANDARD;
transparent = false;
resizable = true;
maximizable = true;
minimizable = true;

systemChrome 能采用的值是在 NativeWindowSystemChrome里定义的。现在的Alpha版只能使用以下的 2种。

Code:
public static const STANDARD:String // 使用标准OS的Chrome
public static const NONE:String // 不使用标准OS的Chrome

如果把NativeWindowSystemChrome.指定为NONE,就没有chrome,也就是说只表示框框内侧的窗口。

以下为打开新的Apollo窗口函数的例子。
Code:Actionscript
public function createNewWindow():void {
// 作成窗口初始化选项
var options:NativeWindowInitOptions = new NativeWindowInitOptions();
// 在这里按照必要设定选项

// 窗口的作成
var newWindow:NativeWindow = new NativeWindow(false,options);

// 在这里对窗口进行必要的处理

// 让窗口显示
newWindow.visible = true;
}

owner 属性

NativeWindowInitOptions 里有一个 owner 的属性。能指定新的Apollo窗口的所有者(父窗口)。

如果新窗口指定了owner的话,新窗口一定会在自己的 owner 上面显示(会遮住)。即使焦点在owner 窗口上,彼此的重叠顺序也不会变化。

同时,owner 窗口在关闭时,在 owner 里(上)的那个新窗口也全部会关闭。

下的例子是:最初启动的窗口为程序启动后有的窗口的 owner 。所以,关闭最初启动的窗口的话几个开着的窗口也全部会关闭,程序也会结束。

Code:MXML
<?xml version="1.0" encoding="utf-8"?>
<mx:ApolloApplication xmlns:mx="http://www.adobe.com/2006/mxml" width="350" height="200">
<mx:Script>

<![CDATA[
public function createNewWindow():void {
// 作成窗口初始化选项
var options:NativeWindowInitOptions = new NativeWindowInitOptions();
options.owner = stage.window;

// 作成窗口
var newWindow:NativeWindow = new NativeWindow(false,options);
newWindow.width = 400;
newWindow.height = 300;

// 在窗口里追加text field
newWindow.stage.align = StageAlign.TOP_LEFT;
newWindow.stage.scaleMode = StageScaleMode.NO_SCALE;
var tf:TextField = new TextField();
tf.width = newWindow.width;
tf.text = "这是空窗口";
newWindow.stage.addChild(tf);

// 让窗口显示
newWindow.visible = true;
}
]]>
</mx:Script>
<mx:Button label="打开窗口" click="createNewWindow();"/>
</mx:ApolloApplication>

注意,作为Alpha版的限制 ,Flex的组件不能添加。这个例子使用的是text field。

2007-04-21

Flash是否发展到极限了?

以前写过一篇文章Flash CS3 = Flash 8 + AS3.0 + CS3 UI ? 今天真正用了一下,彻底让我失望。
  1. 实在是太大了,1.2G!有点难以容忍。
  2. 代码编辑功能太差,跟Flash 8差不多,跟FlexBuilder差远了。
  3. 将动画转换为XML,好像只能在Flash里用(无法在Flex里用)。
  4. 用户界面组件,比Flex的差太多,大概为Flex的简化版。
  5. 丰富的绘图功能,DrawingObject却不在了。
  6. Adobe 界面,可以说没有实质的改变。
只有fl.*package有点动心。 看来以后只有flash + flex结合了:(

2007-04-16

Adobe CS3 英文版出货开始了!

Adobe CS3在美国正式出货了!(Adobe Ships Creative Suite 3

关于Flash CS3,变为不但有AS3,还有跟Illustrator 和 photoshop的整合强化等内容的升级。相当于旧 Macromedia Studio的Web Standard CS3售价$999左右。再加上Photoshop, Illusutrator, Acrobat Web Premium CS3售价 $1,599左右。详细请看这边(Adobe Creative Suite 3 Web Editions

并且Premire Pro CS3 和 After Effects CS3 的预览版在 Adobe Labs 公开了。(Adobe Premire Pro CS3@Labs, Adobe After Effects CS3@Labs) Premire 好象只支持 Intel Mac 。After Effects 还支持 PowerPC Mac 。据说预定在今年的夏天出货。

2007-04-13

Flash Player 9 更新

Flash Player 9 更新了。最新版是 9.0.45.0 ,拥有Win版和Mac版。 主要目的为对应将要发布的Flash CS3 Professional。修正了以下项目:
  • Flash CS3 Professional 的新的AS3组件不能正确工作。
  • 用gotoAndStop等帧移动来生成的AS3的对象有可能不能正常工作。
  • AS3用的RuntimeShareLibrary(RSL)执行时出现安全性错误。
  • flash.text.TextField.getCharBoundaries的返回领域会向左移2px。
更详细的问题的解说在以下的Technote。(为英文)

2007-04-08

盗版与正版的区别是什么?

一般来说,盗版有可能出现

  1. 盘读不起
  2. 盘容易坏
  3. 内容与封面不符
  4. 有病毒
  5. ...
但“正版”不会。

前几天,在大连花了45元买的一套正版的世界进行曲的光碟(两盘装的)。用 CD player播放时竟然会出现爆音(读到中途读不走,因而反复重读)!没办法,我只好把它拷贝到电脑上,谁知A,B两面的歌的ID3(附加的信息)的名字竟然A,B一模一样!而且封面有多处错误。

这还是正版吗?这还称得上正版吗?或许还不如10元的盗版。

盗版与正版的区别到底是什么?中国的产品质量何时才能提高?

2007-04-05

Apollo窗口的设置

消除OS窗口框架

首先,变更程序配置文件(程序名-app.xml) 里 rootContent 标签。

rootContent 标签的 systemChrome 为 "standard" 时,为 OS 标准的窗口;"none"时,为 Apollo 程序提供的窗口框架。

<rootcontent systemchrome="none" transparent="false" visible="true">[SWF reference is generated]</rootcontent>

按照上面,把 systemChrome 设为 "none",制作一个空的Apollo程序。

<?xml version="1.0" encoding="utf-8"?> <mx:ApolloApplication mx="http://www.adobe.com/2006/mxml"> </mx:ApolloApplication>

执行后,应该会表示以下画面:

Apollo Application Sample

不想使用Apollo 提供的窗口框架时,把 Apollo 程序(程序名.mxml)的根节点从ApolloApplication变为Application。

<?xml version="1.0" encoding="utf-8"?> <mx:Application mx="http://www.adobe.com/2006/mxml"> </mx:Application>

执行后,应该会表示以下画面:

Apollo Application Sample

去掉背景

接着,去掉四方的背景。

首先,在序配置文件(程序名-app.xml)内的 rootContent 标签里有一个 transparent 的属性。把它设为true。

<rootContent systemChrome="none" transparent="true" visible="true">[SWF reference is generated]</rootContent>

只有这些,背景还不会变。还要设置Application的CSS属性:

background-color:""; background-image:"";

这样的话,程序的背景就变为透明的了。

也就意味着执行的程序什么也看不到。

以下为全部代码:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Style>
Application {
 background-color:"";
 background-image:"";
}
</mx:Style>
<!--一张图片-->
<mx:Image source="myImage.png"/>

</mx:Application>

2007-04-02

No MS! - 对Microsoft说 NO!

对Microsoft说 NO!

Microsoft不是恶霸。no ms 但是太“强”了,并且用户已经受到了损害! 它正在限制着其他的有用的软件。

屡次,Microsoft(以下简称MS)精选和分类软件,并且运用巨大的资源和在Windows开发者的地位,任意地铲除或残忍地削弱竞争对手。但是,MS的产品并不比其他的好。MS要求厂家捆绑Windows在厂家销售的所有的计算机里,但不提供其他的操作系统(参照BeOS)。MS也用同样的手段让MS office预先安装在新的计算机里,并且禁止其他的浏览器预先安装在标准用户桌面上。所以竞争对手没有平等的机会销售他们的产品。最终的结果是我们只有更少的浏览器可以选择,更少的文字处理器,更少的操作系统…

更少的竞争带来了更少的真正的革新和改良。真正能得到市场的新的想法被迫为MS效劳。真正的改良一去不复返,或变得异常的慢。它意味着更低的坚固性,更少的好软件,更高的价格…更新或升级只是为了保持用户的使用率。MS那样地阻止其他的新的企业拥有立足的空间来直接地对抗。美国政府(大部分)不会也不将管理这些事,因为MS给与了他们大量的支持。这是一个巨大的MS的计谋,为了达到他的最终目标:MS的产品在所有的计算机上。如果你使用任何MS的产品,将会助MS一臂之力。最终将成为独家的企业!

没有谁能够让它停止!

除了你。

你可以选择是否用MS让你买的,或者想一想自己,选择一个自己喜欢的。 你可以选择其他来源的产品,或更好的更便宜的。 你可以做出对Microsoft说 NO!的选择

Just Say No to Microsoft(en)

2007-04-01

capture与bubbles详解

所有 在DisplayList 上的渲染单位都支持全新的三段式事件播放机制,以 Stage 为起点自上而下的播报事件到 target 对象(此过程称为 Capture Phase),然后播报事件给 target 对象(此过程称为 Target Phase),最后在自下而上的播报事件(此过程称为 Bubbling Phase)。 示意图如下:(点击播放,动画的GIF) 添加方法为: //Target Phase + Bubbling Phase Child.addEventListener(MouseEvent.CLICK, childCleckHandler, false); //Capture Phase Child.addEventListener(MouseEvent.CLICK, childCleckHandler, true); //如果两个都添加的话,就要写两遍(useCapture一次为true,一次为false) Child.addEventListener(MouseEvent.CLICK, childCleckHandler, true); Child.addEventListener(MouseEvent.CLICK, childCleckHandler, false); 一个例子(要在Flex2的debug模式下才能运行):Sample.as
package {
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.events.Event;

public class Sample extends Sprite {

    public function Sample() {
        //Parent
        with(graphics) {
            lineStyle(1,0x000000);
            beginFill(0x993300)
            moveTo(0,0);
            lineTo(550,0);
            lineTo(550,550);
            lineTo(0,550);
            lineTo(0,0);
            endFill();
        }
        addEventListener(MouseEvent.CLICK, parentCleckHandler,true);
        addEventListener(MouseEvent.CLICK, parentCleckHandler);
        //Self
        var self:Sprite = new Sprite();
        with(self.graphics) {
            lineStyle(1,0x000000);
            beginFill(0x003399)
            moveTo(50,50);
            lineTo(500,50);
            lineTo(500,500);
            lineTo(50,500);
            lineTo(50,50);
            endFill();
        }
        self.addEventListener(MouseEvent.CLICK, selfCleckHandler,true);
        self.addEventListener(MouseEvent.CLICK, selfCleckHandler);
        //Child
        addChild(self)
        var child:Sprite = new Sprite();
        with(child.graphics) {
            lineStyle(1,0x000000);
            beginFill(0x993399)
            moveTo(100,100);
            lineTo(450,100);
            lineTo(450,450);
            lineTo(100,450);
            lineTo(100,100);
            endFill();
        }
        child.addEventListener(MouseEvent.CLICK, childCleckHandler,true);
        child.addEventListener(MouseEvent.CLICK, childCleckHandler);
        self.addChild(child)
    }
    private function parentCleckHandler(event:Event):void {
        trace("Parent clecked!")
    }
    private function selfCleckHandler(event:Event):void {
        trace("\tSelf clecked!")
    }
    private function childCleckHandler(event:Event):void {
        trace("\t\tChild clecked!")
    }
}
}