tag:blogger.com,1999:blog-69349493776589660402008-07-19T15:57:36.904+08:00Ticore's Blog{id: "Ticore"}; //http://www.blogger.com/profile/01433005931305983346noreply@blogger.comBlogger305125tag:blogger.com,1999:blog-6934949377658966040.post-45601614942338772492008-07-19T11:05:00.005+08:002008-07-19T15:57:36.921+08:00Kaspersky Firewall Bug<p align="right" class="author"><a href="http://ticore.blogspot.com/">Ticore's Blog</a></p>
<p>
昨天測試 Flash AS3 Socket 連線時,意外的讓 Windows VISTA 直接進入藍畫面!
</p>
<p>
後來經過反覆測試,似乎與 Windows 無關,XP、VISTA SP 幾都會發生<br/>
主要問題是發生在 Kaspersky Internet Security 7.0.1.325<br/>
而 ActionScript 3.0 作的事情也很簡單,每隔 10 ms 嘗試 Socket 連線到 127.0.0.1:80 而已
</p>
<p>
Kaspersky Internet Security 7.0.0.325 似乎沒有這個問題
</p>
<span class="fullpost">
<p>
使用 Flash Player 測試時,需要注意一下要在本機上跑<br/>
不然會被 Flash Player Sandbox 擋下來的<br/>
另外機器上也不要在 80 port 開 HTTP Server
</p>
<p>
ActionScript 3.0 Socket 測試程式:
</p>
<pre name="code" class="as3:showcolumns">
package {
import flash.display.MovieClip;
import flash.events.IOErrorEvent;
import flash.events.TimerEvent;
import flash.net.Socket;
import flash.utils.Timer;
[SWF(width="300", height="200", backgroundColor="#FFFFFF", frameRate="30")]
public class AS3SocketCrash extends MovieClip {
protected var timer:Timer = new Timer(10);
protected var socket:Socket = new Socket();
public function AS3SocketCrash() {
socket.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
timer.addEventListener(TimerEvent.TIMER, onTimerHandler);
timer.start();
}
private function onTimerHandler(evtObj:TimerEvent):void{
socket.connect("127.0.0.1", 80);
}
private function onIOError(evtObj:IOErrorEvent):void{
trace(evtObj);
}
}
}
// Ticore's Blog - http://ticore.blogspot.com/
</pre>
<p>
以下則是使用 VMWare 測試得到藍畫面
</p>
<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_JHhe1vma7nY/SIFjaoM6fPI/AAAAAAAAAbI/NouhljiJov0/s1600-h/KasperskySocketCrashWin.gif"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp3.blogger.com/_JHhe1vma7nY/SIFjaoM6fPI/AAAAAAAAAbI/NouhljiJov0/s320/KasperskySocketCrashWin.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5224566351845817586" /></a>
</span>{id: "Ticore"}; //http://www.blogger.com/profile/01433005931305983346noreply@blogger.comtag:blogger.com,1999:blog-6934949377658966040.post-5486556577691457112008-07-05T20:07:00.008+08:002008-07-14T18:14:18.828+08:00AS3 - BitmapText 程式分享<p align="right" class="author"><a href="http://ticore.blogspot.com/">Ticore's Blog</a></p>
<p>
由於 Flash Player 一直以來都無法對系統字體的文字作旋轉與不規則形狀遮罩<br/>
可是到了 Flash Player 9 AS3,可以將文字繪製成點陣圖<br/>
也可以自行繼承內建類別 Sprite, TextField 等<br/>
於是想到做一個 TextField Wrapper,提供系統文字的點陣化功能<br/>
藉以達到文字可旋轉、套用不規則遮罩
</p>
<p>
其實這個 BitmapText 程式去年就已經寫了<br/>
主要是出於研究目的<br/>
專案一次也沒有用到過<br/>
沒想到最近新出的 Flash Player 10 beta 文字引擎<br/>
已經可以使用系統字體作旋轉了<br/>
倘若再不把這程式拿出來使用一下,恐怕就這樣永不見天日了~~><
</p>
<span class="fullpost">
<p>
主要是包含兩個類別 TextWrapper, BitmapText<br/>
TextWrapper 只是 TextField 的外覆類別<br/>
真正在做點陣繪圖的是 BitmapText<br/>
由於 AS3 TextField 成員屬性與方法相當多<br/>
我已經很盡量的複寫大部分的方法了<br/>
</p>
<p>
TextWrapper Class:
</p>
<pre name="code" class="as3:showcolumns:contentHeight[400px]">
/*
TextWrapper AS3 v0.0.2
Date: 2007.04.25
作者: Ticore Shih
Blog:http://ticore.blogspot.com
EMail: swl@ms53.url.com.tw
v0.0.1
繼承 Sprite 包覆一個 TextField
v0.0.2
增加 TextField 一般性方法
*/
package com.ticore.text {
import flash.geom.*;
import flash.display.*;
import flash.text.*;
import flash.events.*;
public class TextWrapper extends Sprite {
//
// Protected Property
//
protected var _txt_:TextField;
//
// Constructor
//
public function TextWrapper() {
init();
}
protected function init():void {
_txt_ = new TextField();
this.addChild(_txt_);
}
//
// Override DisplayObject Property and Method
//
public override function set width(w:Number):void {
_txt_.width = w;
}
public override function get width():Number {
return _txt_.width;
}
public override function set height(h:Number):void {
_txt_.height = h;
}
public override function get height():Number {
return _txt_.height;
}
//
// Proxy Common TextField Property
//
public function set antiAliasType(value:String):void {
_txt_.antiAliasType = value;
}
public function get antiAliasType():String {
return _txt_.antiAliasType;
}
public function set autoSize(value:String):void {
_txt_.autoSize = value;
}
public function get autoSize():String {
return _txt_.autoSize;
}
public function set gridFitType(value:String):void {
_txt_.gridFitType = value;
}
public function get gridFitType():String {
return _txt_.gridFitType;
}
public function set htmlText(value:String):void {
_txt_.htmlText = value;
}
public function get htmlText():String {
return _txt_.htmlText;
}
public function set restrict(value:String):void {
_txt_.restrict = value;
}
public function get restrict():String {
return _txt_.restrict;
}
public function set text(txt:String):void {
_txt_.text = txt;
}
public function get text():String {
return _txt_.text;
}
public function set type(type:String):void {
_txt_.type = type;
}
public function get type():String {
return _txt_.type;
}
public function set backgroundColor(value:uint):void {
_txt_.backgroundColor = value;
}
public function get backgroundColor():uint {
return _txt_.backgroundColor;
}
public function set borderColor(value:uint):void {
_txt_.borderColor = value;
}
public function get borderColor():uint {
return _txt_.borderColor;
}
public function set textColor(value:uint):void {
_txt_.textColor = value;
}
public function get textColor():uint {
return _txt_.textColor;
}
public function get bottomScrollV():int {
return _txt_.bottomScrollV;
}
public function get caretIndex():int {
return _txt_.caretIndex;
}
public function get length():int {
return _txt_.length;
}
public function get maxChars():int {
return _txt_.maxChars;
}
public function get maxScrollH():int {
return _txt_.maxScrollH;
}
public function get maxScrollV():int {
return _txt_.maxScrollV;
}
public function get numLines():int {
return _txt_.numLines;
}
public function get selectionBeginIndex():int {
return _txt_.selectionBeginIndex;
}
public function get selectionEndIndex():int {
return _txt_.selectionEndIndex;
}
public function set sharpness(value:Number):void {
_txt_.sharpness = value;
}
public function get sharpness():Number {
return _txt_.sharpness;
}
public function set thickness(value:Number):void {
_txt_.thickness = value;
}
public function get thickness():Number {
return _txt_.thickness;
}
public function get textHeight():Number {
return _txt_.textHeight;
}
public function get textWidth():Number {
return _txt_.textWidth;
}
public function set alwaysShowSelection(value:Boolean):void {
_txt_.alwaysShowSelection = value;
}
public function get alwaysShowSelection():Boolean {
return _txt_.alwaysShowSelection;
}
public function set border(value:Boolean):void {
_txt_.border = value;
}
public function get border():Boolean {
return _txt_.border;
}
public function set condenseWhite(value:Boolean):void {
_txt_.condenseWhite = value;
}
public function get condenseWhite():Boolean {
return _txt_.condenseWhite;
}
public function set displayAsPassword(value:Boolean):void {
_txt_.displayAsPassword = value;
}
public function get displayAsPassword():Boolean {
return _txt_.displayAsPassword;
}
public function set embedFonts(value:Boolean):void {
_txt_.embedFonts = value;
}
public function get embedFonts():Boolean {
return _txt_.embedFonts;
}
public function set mouseWheelEnabled(value:Boolean):void {
_txt_.mouseWheelEnabled = value;
}
public function get mouseWheelEnabled():Boolean {
return _txt_.mouseWheelEnabled;
}
public function set multiline(value:Boolean):void {
_txt_.multiline = value;
}
public function get multiline():Boolean {
return _txt_.multiline;
}
public function set selectable(value:Boolean):void {
_txt_.selectable = value;
}
public function get selectable():Boolean {
return _txt_.selectable;
}
public function set useRichTextClipboard(value:Boolean):void {
_txt_.useRichTextClipboard = value;
}
public function get useRichTextClipboard():Boolean {
return _txt_.useRichTextClipboard;
}
public function set wordWrap(value:Boolean):void {
_txt_.wordWrap = value;
}
public function get wordWrap():Boolean {
return _txt_.wordWrap;
}
//
// Proxy Common TextField Method
//
public function appendText(text:String):void {
_txt_.appendText(text);
}
public function getCharBoundaries(charIndex:int):Rectangle {
return _txt_.getCharBoundaries(charIndex);
}
public function getCharIndexAtPoint(x:Number, y:Number):int {
return _txt_.getCharIndexAtPoint(x,y);
}
public function getFirstCharInParagraph(charIndex:int):int {
return _txt_.getFirstCharInParagraph(charIndex);
}
public function getImageReference(id:String):DisplayObject {
return _txt_.getImageReference(id);
}
public function getLineIndexAtPoint(x:Number, y:Number):int {
return _txt_.getLineIndexAtPoint(x,y);
}
public function getLineIndexOfChar(charIndex:int):int {
return _txt_.getLineIndexOfChar(charIndex);
}
public function getLineLength(lineIndex:int):int {
return _txt_.getLineLength(lineIndex);
}
public function getLineMetrics(lineIndex:int):TextLineMetrics {
return _txt_.getLineMetrics(lineIndex);
}
public function getLineOffset(lineIndex:int):int {
return _txt_.getLineOffset(lineIndex);
}
public function getLineText(lineIndex:int):String {
return _txt_.getLineText(lineIndex);
}
public function getParagraphLength(charIndex:int):int {
return _txt_.getParagraphLength(charIndex);
}
public function replaceSelectedText(value:String):void {
_txt_.replaceSelectedText(value);
}
public function replaceText(beginIndex:int, endIndex:int, newText:String):void {
_txt_.replaceText(beginIndex,endIndex,newText);
}
public function setTextFormat(format:TextFormat, beginIndex:int = -1, endIndex:int = -1):void {
_txt_.setTextFormat(format,beginIndex,endIndex);
}
public function getTextFormat(beginIndex:int = -1, endIndex:int = -1):TextFormat {
return _txt_.getTextFormat(beginIndex,endIndex);
}
public function set defaultTextFormat(format:TextFormat):void {
_txt_.defaultTextFormat = format;
}
public function get defaultTextFormat():TextFormat {
return _txt_.defaultTextFormat;
}
}
}
</pre>
<p>
BitmapText Class:
</p>
<pre name="code" class="as3:showcolumns:contentHeight[400px]">
/*
BitmapText AS3 v0.0.4
Date: 2007.04.25
作者: Ticore Shih
Blog:http://ticore.blogspot.com
EMail: swl@ms53.url.com.tw
v0.0.1
利用 BitmapData draw TextFIeld
達到可以呈現旋轉文字的效果
v0.0.2
增加 TextField 一般性方法與屬性控制
增加 validate 屬性,減少不必要 draw 次數
TextField.autoSize 功能會有一些問題
TextField 大小會一直跳動,重複 draw 會發生多重影像
v0.0.3
增加 TextField 一般性方法與屬性控制
v0.0.4
重構將 TextWrapper 功能獨立為單一 Class
*/
package com.ticore.text {
import flash.geom.*;
import flash.display.*;
import flash.text.*;
import flash.events.*;
import flash.filters.*;
public class BitmapText extends TextWrapper {
// Private Property
private var _validate_:Boolean = true;
private var magniFactor:Number = 3;
private var blurFilter:BlurFilter;
private var _useBitmapText_:Boolean = true;
private var bmpData:BitmapData;
private var bmp:Bitmap;
public function BitmapText() {
init();
}
protected override function init():void {
super.init();
_txt_.addEventListener(Event.CHANGE, onChange);
bmp = new Bitmap();
bmp.smoothing = true;
bmp.scaleX = bmp.scaleY = 1 / magniFactor;
this.addChild(bmp);
_txt_.visible = false;
this.addChild(_txt_);
blurFilter = new BlurFilter(1 + magniFactor / 6, 1 + magniFactor / 6, BitmapFilterQuality.MEDIUM);
validate = false;
addEventListener(Event.ENTER_FRAME, onEnterFame);
}
//
// Private Method
//
private function updateBmpData():void {
if (bmpData) {
bmpData.dispose();
}
bmpData = new BitmapData((width + 1) * magniFactor, (height + 1) * magniFactor, true, 0x00000000);
bmp.bitmapData = bmpData;
bmp.smoothing = true;
validate = false;
}
private function onChange(eventObj:Event):void {
validate = false;
}
private function onEnterFame(eventObj:Event):void {
if (!validate) {
draw();
}
}
private function draw():void {
if (bmpData == null) {
updateBmpData();
}
if (bmpData.width < (width + 1) * magniFactor || bmpData.height < (height + 1) * magniFactor) {
updateBmpData();
}
var rect:Rectangle = new Rectangle(_txt_.x, _txt_.y, _txt_.width, _txt_.height);
bmpData.fillRect(bmpData.rect, 0x00000000);
var xOffset:Number = -_txt_.x;
var dev:Number = magniFactor / 3;
bmpData.draw(_txt_, new Matrix(magniFactor, 0, 0, magniFactor, xOffset * magniFactor + 0, 0));
bmpData.draw(_txt_, new Matrix(magniFactor, 0, 0, magniFactor, xOffset * magniFactor + dev, 0));
bmpData.draw(_txt_, new Matrix(magniFactor, 0, 0, magniFactor, xOffset * magniFactor + 0, dev));
bmpData.applyFilter(bmpData, bmpData.rect, new Point(0, 0), blurFilter);
bmpData.draw(_txt_, new Matrix(magniFactor, 0, 0, magniFactor, xOffset * magniFactor + dev / 2, dev / 2));
bmp.x = _txt_.x;
bmp.y = _txt_.y;
validate = true;
}
//
// Public Method
//
public function set validate(value:Boolean):void {
_validate_ = value;
}
public function get validate():Boolean {
return _validate_;
}
public function set useBitmapText(value:Boolean):void {
_useBitmapText_ = value;
_txt_.visible = !value;
bmp.visible = value;
}
public function get useBitmapText():Boolean {
return _useBitmapText_;
}
//
// Override Method
//
public override function set width(w:Number):void {
super.width = w;
validate = false;
}
public override function set height(h:Number):void {
super.height = h;
validate = false;
}
public override function appendText(text:String):void {
super.appendText(text);
validate = false;
}
public override function replaceSelectedText(value:String):void {
super.replaceSelectedText(value);
validate = false;
}
public override function replaceText(beginIndex:int, endIndex:int, newText:String):void {
super.replaceText(beginIndex,endIndex,newText);
validate = false;
}
public override function setTextFormat(format:TextFormat, beginIndex:int = -1, endIndex:int = -1):void {
super.setTextFormat(format,beginIndex,endIndex);
validate = false;
}
public override function set defaultTextFormat(format:TextFormat):void {
super.defaultTextFormat = format;
validate = false;
}
public override function set antiAliasType(value:String):void {
super.antiAliasType = value;
validate = false;
}
public override function set autoSize(value:String):void {
super.autoSize = value;
validate = false;
}
public override function set gridFitType(value:String):void {
super.gridFitType = value;
validate = false;
}
public override function set htmlText(value:String):void {
super.htmlText = value;
validate = false;
}
public override function set restrict(value:String):void {
super.restrict = value;
validate = false;
}
public override function set text(value:String):void {
super.text = value;
validate = false;
}
public override function set backgroundColor(value:uint):void {
super.backgroundColor = value;
validate = false;
}
public override function set borderColor(value:uint):void {
super.borderColor = value;
validate = false;
}
public override function set textColor(value:uint):void {
super.textColor = value;
validate = false;
}
public override function set sharpness(value:Number):void {
super.sharpness = value;
validate = false;
}
public override function set thickness(value:Number):void {
super.thickness = value;
validate = false;
}
public override function set alwaysShowSelection(value:Boolean):void {
super.alwaysShowSelection = value;
validate = false;
}
public override function set border(value:Boolean):void {
super.border = value;
validate = false;
}
public override function set condenseWhite(value:Boolean):void {
super.condenseWhite = value;
validate = false;
}
public override function set displayAsPassword(value:Boolean):void {
super.displayAsPassword = value;
validate = false;
}
public override function set embedFonts(value:Boolean):void {
super.embedFonts = value;
validate = false;
}
public override function set multiline(value:Boolean):void {
super.multiline = value;
validate = false;
}
public override function set selectable(value:Boolean):void {
super.selectable = value;
validate = false;
}
public override function set wordWrap(value:Boolean):void {
super.wordWrap = value;
validate = false;
}
}
}
</pre>
<p>
測試程式如下:
</p>
<pre name="code" class="as3:showcolumns">
import com.ticore.text.*;
var bmpTxt:BitmapText = new BitmapText();
this.addChild(bmpTxt);
bmpTxt.border = true;
bmpTxt.multiline = true;
bmpTxt.rotation = 0;
bmpTxt.wordWrap = true;
bmpTxt.rotation = 15;
bmpTxt.width = 320;
bmpTxt.height = 250;
bmpTxt.x = 170;
bmpTxt.y = 30;
var format:TextFormat = bmpTxt.getTextFormat();
format.font = "新細明體";
format.align = "center";
for (var i:Number = 6; i <= 22; ++i) {
format.size = i;
bmpTxt.defaultTextFormat = format;
bmpTxt.appendText("Font Size " + format.size + " 新細明體\n");
}
</pre>
<p>
<a href="http://riafiles.googlepages.com/BitmapText_0.0.5.zip">原始檔案下載</a>
</p>
<p>
實際執行效果擷圖:
</p>
<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_JHhe1vma7nY/SG9pUTEQDJI/AAAAAAAAAbA/pjOWlfY-sLE/s1600-h/BitmapTextDemo.gif"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp2.blogger.com/_JHhe1vma7nY/SG9pUTEQDJI/AAAAAAAAAbA/pjOWlfY-sLE/s320/BitmapTextDemo.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5219506290582097042" /></a>
<p>
看起來應該還不錯吧!<br/>
即使在旋轉狀態下也沒有很嚴重的鋸齒<br/>
我特別在繪製點陣圖步驟提升了解析度<br/>
並且作了偏移繪製,套用濾鏡<br/>
當然這些動作是會消耗效能的<br/>
所以只有在必要時才會進行重繪的動作
</p>
</span>{id: "Ticore"}; //http://www.blogger.com/profile/01433005931305983346noreply@blogger.comtag:blogger.com,1999:blog-6934949377658966040.post-64335703169697582612008-07-03T10:23:00.004+08:002008-07-14T18:14:18.983+08:00Adobe Flash Player 10 beta 2 出了<p align="right" class="author"><a href="http://ticore.blogspot.com/">Ticore's Blog</a></p>
<p>
<a target="_blank" href="http://labs.adobe.com/technologies/flashplayer10/">Adobe Flash Player 10 beta 2</a> 出了<br/>
其中有一個很重要的新功能 Loader.unloadAndStop(gc:Boolean = true):void<br/>
呼叫之後可以立即移除 SWF 內所有的音樂、Event Listeners、Timers、....
</p>
<span class="fullpost">
<p>
文件上的說明:
</p>
<code> public function unloadAndStop(gc:<a href="../../Boolean.html">Boolean</a> = true):<a href="../../specialTypes.html#void">void</a></code>
<p>
Attempts to unload child SWF file contents and stops the execution of commands from loaded SWF files. This method attempts to unload SWF files
that were loaded using <code>Loader.load()</code> or <code>Loader.loadBytes()</code> by removing references to EventDispatcher, NetConnection, Timer, Sound, or Video objects of the child SWF file. As a result, the following occurs for the child SWF file and the child SWF file's display list:
</p>
<ul>
<li>Sounds are stopped.</li>
<li>Stage event listeners are removed.</li>
<li>Event listeners for <code>enterFrame</code>, <code>frameConstructed</code>, <code>exitFrame</code>, <code>activate</code> and <code>deactivate</code> are removed.</li>
<li>Timers are stopped.</li>
<li>Camera and Microphone instances are detached</li><li>Movie clips are stopped.</li>
</ul>
<p>
發現一點很奇妙的事情,beta 2 的版本號碼居然比 beta 1 還少<br/>
Release Note 上寫得很清楚:(我有把 Release Note 都存下來)
</p>
<p>
<b>Updated: May 15, 2008</b><br/>
These release notes document known issues related to the beta versions of Adobe® Flash® Player 10, code named
“Astro”. The current beta build <b>10.0.1.218</b>.
</p>
<p>
<b>Updated: July 2, 2008</b>
These release notes document known issues related to the beta versions of Adobe® Flash® Player 10, code named "Astro". The current beta build <b>10.0.0.525</b>.
</p>
<p>
難道 Flash Player 原始碼也被回溯了嗎? :P
</p>
</span>{id: "Ticore"}; //http://www.blogger.com/profile/01433005931305983346noreply@blogger.comtag:blogger.com,1999:blog-6934949377658966040.post-52782036296790387692008-06-27T00:53:00.008+08:002008-07-14T18:17:47.921+08:00Flex 技巧 - 將資料綁定封裝起來<p align="right" class="author"><a href="http://ticore.blogspot.com/">Ticore's Blog</a></p>
<p>
之前介紹了 <a href="http://ticore.blogspot.com/2008/06/flex-databinding-manually.html">純手工設定 Flex DataBinding 的方式</a><br/>
不過那挺麻煩的<br/>
假如想要將 DataBinding 封裝起來,保留部分彈性<br/>
又不想要那麼麻煩的設定方式<br/>
不妨可以試試看以下的方式
</p>
<span class="fullpost">
<p>
在這個例子中,完全的將 DataBinding 封裝在一個 MXML Component 中<br/>
必須要指定好目標物,Component 內的 DataBinding 才會發生作用<br/>
想要停止 DataBinding 也很簡單,只要將目標屬性設為 null 就好
</p>
<p>
甚至可以對一份資料,準備多個 DataBinding Component<br/>
只要在執行期動態替換 Component,就能達到切換 DataBinding 行為的目的<br/>
其實還挺方便的
</p>
<p>
Main.mxml:
</p>
<pre name="code" class="mxml:showcolumns">
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
verticalAlign="middle" backgroundColor="#FFFFFF"
creationComplete="init();" fontSize="12">
<mx:Script>
<![CDATA[
public var comp:BindingComp;
public function init():void{
comp = new BindingComp();
comp.initialize();
}
]]>
</mx:Script>
<mx:HBox>
<mx:Label text="No 1:" />
<mx:NumericStepper id="no1" maximum="100" />
</mx:HBox>
<mx:HBox>
<mx:Label text="No 2:" />
<mx:NumericStepper id="no2" maximum="100" />
</mx:HBox>
<mx:CheckBox id="chk" label="DataBinding Enabled"
change="comp.target = chk.selected ? this : null;" />
</mx:Application>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->
</pre>
<p>
BindingComp.mxml:
</p>
<pre name="code" class="mxml:showcolumns">
<?xml version="1.0" encoding="utf-8"?>
<mx:UIComponent xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
[Bindable]
public var target:Main;
public function doBinding1(... args:*):void{
if (target) target.no2.value = target.no1.value;
}
public function doBinding2(... args:*):void{
if (target) target.no1.value = target.no2.value;
}
]]>
</mx:Script>
<mx:Model>
{doBinding1(target.no1.value)}
</mx:Model>
<mx:Model>
{doBinding2(target.no2.value)}
</mx:Model>
</mx:UIComponent>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->
</pre>
<p>線上測示範例:</p>
<p>
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,28,0" width="100%" height="200">
<param name="movie" value="http://riafiles.googlepages.com/EncapsulateDataBinding.swf" />
<param name="wmode" value="opaque" />
<embed src="http://riafiles.googlepages.com/EncapsulateDataBinding.swf" pluginspage="http://www.adobe.com/shockwave/download/download.cgi?P1_Prod_Version=ShockwaveFlash" type="application/x-shockwave-flash" width="100%" height="200" wmode="opaque"></embed>
</object>
</p>
<p>
相關連結:<br/>
<a href="http://ticore.blogspot.com/2008/06/flex-databinding-manually.html">Flex - 純手工設定 DataBinding 的方式</a><br/>
<a href="http://ticore.blogspot.com/2008/06/flex-bindingmanager-usage.html">Flex 技巧 - BindingManager 使用方式</a><br/>
<a href="http://ticore.blogspot.com/2008/06/flex-tip-monitor-data-binding.html">Flex 技巧 - 觀察 Data Binding 資料變化</a><br/>
<a href="http://ticore.blogspot.com/2008/03/flex-tip-bracket-operator-in-data.html">Flex Tip - 在 Data Binding 內使用 [...] 運算子</a><br/>
<a href="http://ticore.blogspot.com/2007/01/flex-2-bindable-metadata-tag.html">Flex 2 Bindable Metadata Tag 背後實際作用</a><br/>
<a href="http://ticore.blogspot.com/2006/12/flex-20-actionscript-30-data-binding.html">Flex 2.0 - 以 ActionScript 3.0 動態設置 Data Binding</a>
</p>
</span>{id: "Ticore"}; //http://www.blogger.com/profile/01433005931305983346noreply@blogger.comtag:blogger.com,1999:blog-6934949377658966040.post-47769768325029006592008-06-25T16:43:00.002+08:002008-07-14T18:19:07.369+08:00關於 MMUG.TW 論壇暫停服務<p align="right" class="author"><a href="http://ticore.blogspot.com/">Ticore's Blog</a></p>
<p>
<a target="_blank" href="http://mmug.com.tw/">台灣 macromedia 使用者俱樂部論壇</a> 因為一些說來話長的原因,暫停服務一陣子!
</p>
<p>
若是您在這段期間有什麼 Flash 的問題 "急著" 想要找人請教與討論的話<br/>
歡迎到 Google Group 平台的 <a target="_blank" href="http://groups.google.com/group/augtw">AUG.TW</a> 繼續發問:<br/>
<a target="_blank" href="http://groups.google.com/group/augtw">http://groups.google.com/group/augtw</a>
</p>
<span class="fullpost">
</span>{id: "Ticore"}; //http://www.blogger.com/profile/01433005931305983346noreply@blogger.comtag:blogger.com,1999:blog-6934949377658966040.post-16105622739236079052008-06-18T20:54:00.007+08:002008-07-14T18:29:45.175+08:00Flex SDK 馬歇爾計畫<p align="right" class="author"><a href="http://ticore.blogspot.com/">Ticore's Blog</a></p>
<p>
<a target="_blank" href="http://opensource.adobe.com/wiki/display/flexsdk/Marshall+Plan">Marshall Plan</a> 原文有點長,主要只有兩件事情:<br/>
</p>
<p>
<ul>
<li>
<p>不同版本交互支援 (Cross-Versioning):<br/>
不同版本 Flex 編譯的 SWFs 可以被放在相同的 SecurityDomain 執行<br/>
但是卻可以有不同的 ApplicationDomain</p>
</li>
<li>
<p>不信任的應用程式支援 (Untrusted Application):<br/>
被載入到不同 SecurityDomain 的 SWFs 將不能存取主應用程式或是 Stage 與其它受限的資源</p>
</li>
</ul>
</p>
<p>
</p>
<span class="fullpost">
<p>
這個計畫將可能會在 Flex 3.1 開始支援<br/>
未來不同版本的 Flex 應用程式可以做混搭了<br/>
個人猜測,這計畫背後更重要的意義是 Flash 與 Flex 應用程式混搭
</p>
<p>
不過在那之前,Adobe 可能要先把 <a href="http://ticore.blogspot.com/2008/05/flex-remoteobject-applicationdomain-bug.html">ApplicationDomain 的 Bug</a> 處理掉吧~
</p>
</span>{id: "Ticore"}; //http://www.blogger.com/profile/01433005931305983346noreply@blogger.comtag:blogger.com,1999:blog-6934949377658966040.post-36556789737365387962008-06-17T12:40:00.006+08:002008-07-14T18:28:20.493+08:00Adobe AIR 1.1 出了<p align="right" class="author"><a href="http://ticore.blogspot.com/">Ticore's Blog</a></p>
<p>
<a target="_blank" href="http://www.adobe.com/products/air/">Adobe AIR 1.1</a> 出了,HTML Input Text 終於支援雙位元文字輸入法了
</p>
<span class="fullpost">
<p>
<a target="_blank" href="http://www.adobe.com/products/air/tools/sdk/">Download Adobe AIR SDK</a><br/>
<a target="_blank" href="http://www.adobe.com/products/air/tools/ajax/">Adobe AIR extension for Dreamweaver CS3</a><br/>
<a target="_blank" href="http://kb.adobe.com/selfservice/viewContent.do?externalId=kb403682&sliceId=1">Installing Adobe Air 1.1 Update for Flash CS3 Professional</a><br/>
</p>
<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_JHhe1vma7nY/SFdAfoptmoI/AAAAAAAAAaU/ojsBveviUkw/s1600-h/AIR_1.1_Input.gif"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp0.blogger.com/_JHhe1vma7nY/SFdAfoptmoI/AAAAAAAAAaU/ojsBveviUkw/s320/AIR_1.1_Input.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5212706005937134210" /></a>
</span>{id: "Ticore"}; //http://www.blogger.com/profile/01433005931305983346noreply@blogger.comtag:blogger.com,1999:blog-6934949377658966040.post-69051563164968526322008-06-14T02:00:00.006+08:002008-07-14T18:17:47.922+08:00AS 技巧 - Layer BlendMode 的用處<p align="right" class="author"><a href="http://ticore.blogspot.com/">Ticore's Blog</a></p>
<p>
Flash Player 8 新增的混合模式功能中的圖層模式 (Layer)<br/>
一般使用起來或許覺得沒有什麼特別的用處<br/>
說明文件上寫得更是令人霧茫茫<br/>
簡單的說,只是讓 DisplayObject 子物件預先混和顏色而已
</p>
<span class="fullpost">
<p>
基本上,除了 Normal 之外的混合模式,都會強迫預先混和子物件顏色<br/>
但是其它混合模式都是有特殊效果的<br/>
假如不需要那些效果,但是又要強迫預先混合顏色時<br/>
就要用 Layer 混合模式了
</p>
<p>
對於像是 Flex 這樣由大量的 DisplayObject 組合而成的組件<br/>
遇到需要淡入、淡出效果時<br/>
即使是在最外層設定 Alpha 透明度<br/>
每個子物件仍會先被單獨套用 Alpha 效果再疊合成一張圖<br/>
這樣就會有某些位置顏色特別突兀不透明
</p>
</p>
此時 Layer 混合模式就非常好用了<br/>
它可以讓整個表單先疊合成一張圖再進行 Alpha 效果<br/>
可以確保組件顏色看起來不會特別突兀
</p>
<p>
以下是用 Flex 作的簡單測試<br/>
可以容易觀察到多層巢狀組件在不同 Alpha, BlendMode 的效果
</p>
<pre name="code" class="mxml:showcolumns:contentHeight[400px]">
<?xml version="1.0"?>
<mx:Application layout="vertical" fontSize="12" backgroundColor="#FFFFFF"
xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Style>
HBox.whiteBox {
paddingTop: 15px;
paddingBottom: 15px;
paddingLeft: 15px;
paddingRight: 15px;
backgroundColor: #000000;
}
</mx:Style>
<mx:HBox styleName="whiteBox" alpha="{alphaSlider.value}"
blendMode="{blendModeCb.value ? blendModeCb.value : 'normal'}">
<mx:HBox styleName="whiteBox">
<mx:HBox styleName="whiteBox">
<mx:HBox styleName="whiteBox" />
</mx:HBox>
</mx:HBox>
</mx:HBox>
<mx:HRule width="100%" />
<mx:HBox verticalAlign="middle">
<mx:Label text="BlendMode: " />
<mx:ComboBox id="blendModeCb">
<mx:dataProvider>
["normal", "layer", "darken", "invert", "hardlight"]
</mx:dataProvider>
</mx:ComboBox>
</mx:HBox>
<mx:HBox verticalAlign="middle">
<mx:Label text="Alpha: " />
<mx:HSlider id="alphaSlider" value="0.5"
tickValues="[0, 0.5, 1]" labels="[0, 0.5, 1]"
minimum="0" maximum="1" liveDragging="true" />
</mx:HBox>
</mx:Application>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->
</pre>
<p>
線上測示範例:
</p>
<p>
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,28,0" width="100%" height="250">
<param name="wmode" value="opaque" />
<param name="movie" value="http://riafiles.googlepages.com/LayerBlendModeDemo.swf" />
<embed src="http://riafiles.googlepages.com/LayerBlendModeDemo.swf" width="100%" height="250" wmode="opaque" pluginspage="http://www.adobe.com/shockwave/download/download.cgi?P1_Prod_Version=ShockwaveFlash" type="application/x-shockwave-flash"></embed>
</object>
</p>
<p>
相關連結:<br/>
<a href="http://ticore.blogspot.com/2007/11/flex-label-alpha-tip.html">Flex Label, TextField 半透明小技巧</a><br/>
<a href="http://ticore.blogspot.com/2006/12/flash-8.html">Flash 8 半透明輸入、動態文字欄位</a>
</p>
</span>{id: "Ticore"}; //http://www.blogger.com/profile/01433005931305983346noreply@blogger.comtag:blogger.com,1999:blog-6934949377658966040.post-5212795716109427052008-06-10T00:56:00.007+08:002008-07-14T18:17:47.924+08:00Flex - 純手工設定 DataBinding 的方式<p align="right" class="author"><a href="http://ticore.blogspot.com/">Ticore's Blog</a></p>
<p>
Flex 的 DataBinding Expression 功能雖然非常方便<br/>
不用自行呼叫 addEventListener,省去了不少程式碼<br/>
但是換個角度看,Flex DataBinding 其實是有點缺乏彈性<br/>
不用自行加入監聽事件,同時也意味著不能移除監聽事件
</p>
<p>
然而,自行利用 addEventListener 方式實作的 DataBinding<br/>
感覺好像又沒有 Flex Compiler 產生的好~<br/>
於是想要觀察 Flex Compiler 產生的程式碼<br/>
進而自行模仿實作 DataBinding
</p>
<span class="fullpost">
<p>
想要觀察 Flex Compiler 產生的 ActionScript 很簡單<br/>
只要加入編譯參數 <code>-keep-generated-actionscript=true</code><br/>
就可以在 /src/generated 下找到了
</p>
<p>
舉例來說,想要模擬以下的 DataBinding Expression:
</p>
<pre name="code" class="mxml:showcolumns">
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
backgroundColor="#FFFFFF" layout="vertical" fontSize="12">
<mx:Label text="Binding Source:" />
<mx:HSlider id="slider1" snapInterval="1" maximum="100" value="50" />
<mx:Label text="Binding Destination:" />
<mx:HSlider id="slider2" snapInterval="1" maximum="100" value="{slider1.value}" />
</mx:Application>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->
</pre>
<p>
步驟有點多~~</p>
<ol>
<li>
<p>實作 <code>mx.binding.IBindingClient;</code> 介面</p>
</li>
<li>
<p>
匯入必要的 Class:<br/>
<pre>
import mx.binding.*;
import mx.binding.utils.*;
import mx.core.mx_internal;
</pre>
</p>
</li>
<li>
<p>
宣告 Bindings, Watchers 等屬性:<br/>
<pre>
mx_internal var _bindings : Array = [];
mx_internal var _watchers : Array = [];
mx_internal var _bindingsByDestination : Object = {};
mx_internal var _bindingsBeginWithWord : Object = {};
</pre>
</p>
</li>
<li>
<p>
建立 Bindings 與 Watchers:<br/>
<pre>
mx_internal::_bindings[0] = new Binding(this,
function():* {return slider1.value;},
function(sourceReturnValue:*):void {slider2.value = sourceReturnValue;},
"slider2.value");
mx_internal::_watchers[0] = new PropertyWatcher("slider1",
{propertyChange: true},
[mx_internal::_bindings[0]],
function(propertyName:String):* { return this[propertyName]; });
mx_internal::_watchers[1] = new PropertyWatcher("value",
{valueCommit: true, change: true},
[mx_internal::_bindings[0]], null);
mx_internal::_watchers[0].updateParent(this);
mx_internal::_watchers[0].addChild(mx_internal::_watchers[1]);
mx_internal::_bindings[0].execute();
</pre>
</p>
</li>
</ol>
<p>
最後一個步驟看起來就有點複雜了<br/>
Binding 的功能有點類似 Event Handler,負責執行 DataBinding 運算<br/>
而 Watcher 則是類似 Event Listener,負責監聽資料來源的變化<br/>
為什麼不用標準的 Event Listener 機制<br/>
看 Flex Source 上寫的是因為效能考量
</p>
<p>
先看一下 mx.binding.Binding 類別的使用方式<br/>
<code>public function Binding(document:Object, srcFunc:Function, destFunc:Function, destString:String)</code><br/>
<ul>
<li>document: binding 目標的文件</li>
<li>srcFunc: 用來取值的函式</li>
<li>destFunc: 將值指定到目的地的函式</li>
<li>destString: 用來告訴 ValidationManager 驗證該欄位</li>
</ul>
</p>
<p>
至於 Watcher 其實只是一個上層類別<br/>
實際使用時,需要視 Binding Source 種類決定使用哪一種子 Watcher<br/>
<code>XMLWatcher, PropertyWatcher, StaticPropertyWatcher, RepeaterItemWatcher, RepeaterComponentWatcher,
FunctionReturnWatcher, ArrayElementWatcher</code>
</p>
<p>
Watcher 有一個最特別的地方是,它具有父子關係<br/>
上層的父 Watcher 會觸發下層的子 Watcher 物件<br/>
可以藉由以下 Watcher 函式設定:<br/>
<pre>
public function updateParent(parent:Object):void;
public function addChild(child:Watcher):void;
public function removeChildren(startingIndex:int):void;
public function updateChildren():void;
</pre>
</p>
<p>
綜合上述的步驟<br/>
完整手工設定的 DataBinding MXML 程式碼如下:
</p>
<pre name="code" class="mxml:showcolumns:contentHeight[400px]">
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
backgroundColor="#FFFFFF" layout="vertical" fontSize="12"
implements="mx.binding.IBindingClient"
creationComplete="onCreateComplete();">
<mx:Script>
<![CDATA[
import mx.binding.*;
import mx.binding.utils.*;
import mx.core.mx_internal;
mx_internal var _bindings : Array = [];
mx_internal var _watchers : Array = [];
mx_internal var _bindingsByDestination : Object = {};
mx_internal var _bindingsBeginWithWord : Object = {};
public function onCreateComplete():void{
mx_internal::_bindings[0] = new Binding(this,
function():* {return slider1.value;},
function(sourceReturnValue:*):void {slider2.value = sourceReturnValue;},
"slider2.value");
// mx_internal::_bindings[0].mx_internal::isEnabled = false;
mx_internal::_watchers[0] = new PropertyWatcher("slider1",
{propertyChange: true},
[mx_internal::_bindings[0]],
function(propertyName:String):* { return this[propertyName]; });
mx_internal::_watchers[1] = new PropertyWatcher("value",
{valueCommit: true, change: true},
[mx_internal::_bindings[0]], null);
mx_internal::_watchers[0].updateParent(this);
mx_internal::_watchers[0].addChild(mx_internal::_watchers[1]);
mx_internal::_bindings[0].execute();
// BindingManager.debugBinding("slider2.value");
}
]]>
</mx:Script>
<mx:Label text="Binding Source:" />
<mx:HSlider id="slider1" snapInterval="1" maximum="100" value="50" />
<mx:Label text="Binding Destination:" />
<mx:HSlider id="slider2" snapInterval="1" maximum="100" />
</mx:Application>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->
</pre>
<p>
相關連結:<br/>
<a href="http://ticore.blogspot.com/2008/06/flex-tip-encapsulate-databinding.html">Flex 技巧 - 將資料綁定封裝起來</a><br/>
<a href="http://ticore.blogspot.com/2008/06/flex-bindingmanager-usage.html">Flex 技巧 - BindingManager 使用方式</a><br/>
<a href="http://ticore.blogspot.com/2008/06/flex-tip-monitor-data-binding.html">Flex 技巧 - 觀察 Data Binding 資料變化</a><br/>
<a href="http://ticore.blogspot.com/2008/03/flex-tip-bracket-operator-in-data.html">Flex Tip - 在 Data Binding 內使用 [...] 運算子</a><br/>
<a href="http://ticore.blogspot.com/2007/01/flex-2-bindable-metadata-tag.html">Flex 2 Bindable Metadata Tag 背後實際作用</a><br/>
<a href="http://ticore.blogspot.com/2006/12/flex-20-actionscript-30-data-binding.html">Flex 2.0 - 以 ActionScript 3.0 動態設置 Data Binding</a><br/>
<a target="_blank" href="http://blogs.soph-ware.com/?p=3">Soph-Ware Associates Blog - Data Binding in Flex, Part I</a><br/>
<a target="_blank" href="http://blogs.soph-ware.com/?p=7">Soph-Ware Associates Blog - Data Binding in Flex, Part II</a><br/>
</p>
</span>{id: "Ticore"}; //http://www.blogger.com/profile/01433005931305983346noreply@blogger.comtag:blogger.com,1999:blog-6934949377658966040.post-7552548072068413072008-06-08T17:46:00.004+08:002008-07-14T18:17:47.925+08:00Flex 技巧 - BindingManager 使用方式<p align="right" class="author"><a href="http://ticore.blogspot.com/">Ticore's Blog</a></p>
<p>
Flex 的 mx.binding.*; 內有許多未公開的類別<br/>
主要都是給 MXML Compiler 使用的<br/>
其中 mx.binding.BindingManager 便是負責管理所有的 DataBinding 運作<br/>
BindingManager 內有一些靜態函式還蠻有用的<br/>
列舉如下:
</p>
<span class="fullpost">
<ul>
<li>
<p>
<code>BindingManager.setEnabled(document:Object, isEnabled:Boolean):void;</code><br/>
用來 停止/啟動 Flex Application/Component 內 Data Binding
</p>
</li>
<li>
<p>
<code>BindingManager.executeBindings(document:Object, destStr:String, destObj:Object):void;</code><br/>
執行被指定 Data Binding Expression
</p>
</li>
<li>
<p>
<code>BindingManager.debugBinding(destinationString:String):void;</code><br/>
對指定的 Data Binding Expression 進行除錯
</p>
</li>
</ul>
<p>
以下是簡單的 BindingManager 使用示範程式:
</p>
<pre name="code" class="mxml:showcolumns">
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
backgroundColor="#FFFFFF" layout="vertical" fontSize="12"
creationComplete="onCreateComplete();">
<mx:Script>
<![CDATA[
import mx.binding.*;
public function onCreateComplete():void{
BindingManager.debugBinding("slider2.value");
}
]]>
</mx:Script>
<mx:Label text="Binding Source:" />
<mx:HSlider id="slider1" snapInterval="1" maximum="100" value="50" />
<mx:Label text="Binding Destination:" />
<mx:HSlider id="slider2" snapInterval="1" maximum="100" value="{slider1.value}" />
<mx:CheckBox id="chk" label="Binding Enabled" selected="true"
change="BindingManager.setEnabled(this, chk.selected); btn.enabled = chk.selected;" />
<mx:Button id="btn" label="Execute DataBinding"
click="BindingManager.executeBindings(this, 'slider2.value', null);" />
</mx:Application>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->
</pre>
<p>
測試輸出結果:
</p>
<pre>
Binding: destString = slider2.value, srcFunc result = 54
Binding: destString = slider2.value, srcFunc result = 59
Binding: destString = slider2.value, srcFunc result = 81
Binding: destString = slider2.value, srcFunc result = 41
</pre>
<p>
相關連結:<br/>
<a href="http://ticore.blogspot.com/2008/06/flex-tip-encapsulate-databinding.html">Flex 技巧 - 將資料綁定封裝起來</a><br/>
<a href="http://ticore.blogspot.com/2008/06/flex-databinding-manually.html">Flex - 純手工設定 DataBinding 的方式</a><br/>
<a href="http://ticore.blogspot.com/2008/06/flex-tip-monitor-data-binding.html">Flex 技巧 - 觀察 Data Binding 資料變化</a><br/>
<a href="http://ticore.blogspot.com/2008/03/flex-tip-bracket-operator-in-data.html">Flex Tip - 在 Data Binding 內使用 [...] 運算子</a><br/>
<a href="http://ticore.blogspot.com/2007/01/flex-2-bindable-metadata-tag.html">Flex 2 Bindable Metadata Tag 背後實際作用</a><br/>
<a href="http://ticore.blogspot.com/2006/12/flex-20-actionscript-30-data-binding.html">Flex 2.0 - 以 ActionScript 3.0 動態設置 Data Binding</a><br/>
</p>
</span>{id: "Ticore"}; //http://www.blogger.com/profile/01433005931305983346noreply@blogger.comtag:blogger.com,1999:blog-6934949377658966040.post-62571920058670399542008-06-06T22:00:00.010+08:002008-07-14T18:17:47.927+08:00Flex 技巧 - 觀察 Data Binding 資料變化<p align="right" class="author"><a href="http://ticore.blogspot.com/">Ticore's Blog</a></p>
<p>
Flex Data Binding 功能讓開發者不用寫太多的程式碼<br/>
就能做到資料繫結功能<br/>
但是要除錯的時候就比較不太方便<br/>
Data Binding Expression 區塊內很多語法都不能使用<br/>
當 Data Binding 被觸發時,想要觀察資料變化就不太方便
</p>
<span class="fullpost">
<p>
以下分享一個小技巧,可以很簡單的觀察 Data Binding 前後資料的變化
</p>
<pre name="code" class="mxml:showcolumns">
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
backgroundColor="#FFFFFF" layout="vertical" fontSize="12">
<mx:Label text="Binding Source:" />
<mx:HSlider id="slider1" snapInterval="1" maximum="100" />
<mx:Label text="Binding Destination:" />
<mx:HSlider id="slider2" snapInterval="1" maximum="100"
value="{trace('Before :', slider2.value),
setTimeout(function():void{trace('After :', slider2.value);}, 0), slider1.value}"/>
</mx:Application>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->
</pre>
<p>
由於 Data Binding Expression 內不能使用 ";" 結尾的陳述式<br/>
所以使用 "," 作區隔,只有最後一個 Expression 會被當作值指定給目標<br/>
這樣在前面就可以 trace 到變化之前的值<br/>
配合 setTimeout 又可以觀察到變化之後的值
</p>
<p>
相關連結:<br/>
<a href="http://ticore.blogspot.com/2008/06/flex-tip-encapsulate-databinding.html">Flex 技巧 - 將資料綁定封裝起來</a><br/>
<a href="http://ticore.blogspot.com/2008/06/flex-databinding-manually.html">Flex - 純手工設定 DataBinding 的方式</a><br/>
<a href="http://ticore.blogspot.com/2008/06/flex-bindingmanager-usage.html">Flex 技巧 - BindingManager 使用方式</a><br/>
<a href="http://ticore.blogspot.com/2008/03/flex-tip-bracket-operator-in-data.html">Flex Tip - 在 Data Binding 內使用 [...] 運算子</a><br/>
<a href="http://ticore.blogspot.com/2007/01/flex-2-bindable-metadata-tag.html">Flex 2 Bindable Metadata Tag 背後實際作用</a><br/>
<a href="http://ticore.blogspot.com/2006/12/flex-20-actionscript-30-data-binding.html">Flex 2.0 - 以 ActionScript 3.0 動態設置 Data Binding</a><br/>
</p>
</span>{id: "Ticore"}; //http://www.blogger.com/profile/01433005931305983346noreply@blogger.comtag:blogger.com,1999:blog-6934949377658966040.post-53074317892661190092008-06-03T14:14:00.020+08:002008-07-14T18:14:19.000+08:00Flash 內嵌動態文字與樣式的問題<p align="right" class="author"><a href="http://ticore.blogspot.com/">Ticore's Blog</a></p>
<p>
問題出處:<a target="_blank" href="http://mmug.com.tw/forum/viewtopic.php?f=3&t=12743">動態文字欄位的問題</a>
</p>
<p>
問題描述:
</p>
<p>
於 Flash 舞台上<br/>
放置兩個動態文字欄位,選擇相同的字體<br/>
第一個不嵌入任何字集,樣式設為 regular<br/>
第二個嵌入數字字元集,樣式設為 bold<br/>
於執行期動態重設第二個文字欄位內容<br/>
該文字欄位將無法表現新的文字內容
</p>
<span class="fullpost">
<p>
簡化過後的問題 Demo 程式如下:
</p>
<p>
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,28,0" width="300" height="200">
<param name="movie" value="http://riafiles.googlepages.com/EmbedFontTextFieldIssue.swf" />
<param name="allowScriptAccess" value="always" />
<embed src="http://riafiles.googlepages.com/EmbedFontTextFieldIssue.swf" width="300" height="200" pluginspage="http://www.adobe.com/shockwave/download/download.cgi?P1_Prod_Version=ShockwaveFlash" type="application/x-shockwave-flash" allowscriptaccess="always"></embed>
</object>
</p>
<p>
注意,測試的時候不要先選取 txt2 內的文字<br/>
只要一選取過,就不過出現問題了
</p>
<p><a href="http://riafiles.googlepages.com/EmbedFontTextFieldIssue.zip">原始檔案下載</a></p>
<p>
這個問題其實還挺複雜的,由許多的特性共同影響,分述如下~
</p>
<p>
Flash TextField 與 Embed Font 特性:
</p>
<p>
特性 1.<br/>
基本上,Flash 的內嵌字體,即使是相同的字體名稱<br/>
不同的樣式 (regular, bold, italic) 會被當作完全不同的字體處理
</p>
<p>
特性 2.<br/>
Flash 內所有時間軸預置 TextField 內嵌字體都是可以共用的
</p>
<p>
依據特性 1. 2.,可以做一個簡單的測試<br/>
於 Flash 舞台上放置兩個動態文字欄位<br/>
第一個文字欄位僅嵌入 Airal regular 數字字集<br/>
第二個文字欄位僅嵌入 Airal bold 英文字母字集<br/>
動態將第二個文字欄位樣式設為 regular 之後<br/>
那麼該文字欄位只能表現數字了~~
</p>
<p>
特性 3.<br/>
一個 SWF 內僅嵌入單一字體樣式 (eg. Arial regular) 時<br/>
動態使用同一字體但是不同樣式 (eg. Arial bold) 的文字欄位<br/>
將會使用該字體唯一嵌入樣式 (eg. Arial regular) 作為替代字體
</p>
<p>
特性 4.<br/>
將 TextField.text 內容重設時<br/>
TextField 內的文字樣式 bold, italic 也會被重設為預設的樣式<br/>
AS3 TextField.appendText 則不會重設樣式
</p>
<p>
ActionScript 3.0 測試程式:
</p>
<pre name="code" class="as3:showcolumns:contentHeight[400px]">
package {
import flash.display.*;
import flash.text.*;
public class Main1 extends MovieClip {
public function Main1() {
var txt:TextField = new TextField();
var tf:TextFormat = new TextFormat();
tf.bold = true;
tf.italic = true;
// TextField 內不含文字內容時,無法套用 bold, italic 樣式
txt.text = "";
txt.setTextFormat(tf);
tf = txt.getTextFormat();
trace("tf.bold :",tf.bold,", tf.italic :",tf.italic);
// tf.bold : null , tf.italic : null
txt.text = "123";
txt.setTextFormat(tf);
tf = txt.getTextFormat();
trace("tf.bold :",tf.bold,", tf.italic :",tf.italic);
// tf.bold : true , tf.italic : true
// 改變 TextField.text 內容時,bold, italic 樣式被重設
txt.text="123";
tf = txt.getTextFormat();
trace("tf.bold :",tf.bold,", tf.italic :",tf.italic);
// tf.bold : false , tf.italic : false
tf.bold = true;
tf.italic = true;
txt.setTextFormat(tf);
txt.text += "123";
tf = txt.getTextFormat();
trace("tf.bold :",tf.bold,", tf.italic :",tf.italic);
// tf.bold : false , tf.italic : false
// 使用 appendText 改變 TextField.text 內容時,bold, italic 樣式會被保留
tf.bold = true;
tf.italic = true;
txt.setTextFormat(tf);
txt.appendText("456");
tf = txt.getTextFormat();
trace("tf.bold :",tf.bold,", tf.italic :",tf.italic);
// tf.bold : true , tf.italic : true
// 指定 TextField.text 內容前,呼叫 setSelection,bold, italic 樣式會被保留
tf.bold = true;
tf.italic = true;
txt.setTextFormat(tf);
txt.setSelection(0, 1);
txt.text = "456";
tf = txt.getTextFormat();
trace("tf.bold :",tf.bold,", tf.italic :",tf.italic);
// tf.bold : true , tf.italic : true
// 改變 TextField.text 內容時,bold, italic 會被重設為 defaultTextFormat
tf.bold = true;
tf.italic = false;
txt.setTextFormat(tf);
tf.bold = false;
tf.italic = true;
txt.defaultTextFormat = tf;
txt.text = "456";
tf = txt.getTextFormat();
trace("tf.bold :",tf.bold,", tf.italic :",tf.italic);
// tf.bold : false , tf.italic : true
}
}
}
// Ticore's Blog - http://ticore.blogspot.com/
</pre>
<p>
了解上述特性之後,答案就很明顯了~~<br/>
</p>
<p>
解決方式:<br/>
1. 對於同一字體不同的樣式,均嵌入相同的字集<br/>
2. 當 <code>TextField.text</code> 內容重設時,自行回設正確的 Bold, Italic 樣式<br/>
3. 利用 <code>TextField.defaultTextFormat</code> 設定 Bold, Italic 設定樣式<br/>
4. 於 <code>TextField.text</code> 內容重設之前,呼叫 <code>TextField.setSelection(0, 1);</code>
</p>
<p>
相關連結:<br/>
<a href="http://ticore.blogspot.com/2007/05/flash.html">Flash 技巧 - 預先編譯嵌入字體</a>
</p>
</span>{id: "Ticore"}; //http://www.blogger.com/profile/01433005931305983346noreply@blogger.comtag:blogger.com,1999:blog-6934949377658966040.post-49152387340281224672008-05-31T17:16:00.008+08:002008-07-14T18:17:47.928+08:00Flash 技巧 - 利用 ExternalInterface 完全暫停 Flash Movie 程序<p align="right" class="author"><a href="http://ticore.blogspot.com/">Ticore's Blog</a></p>
<p>
最近在 review 一年半以前發現的技巧時<br/>
<a href="http://ticore.blogspot.com/2006/12/windowprompt-flash.html">『利用 window.prompt 解決 Flash 透明模式下無法輸入中文的問題』</a><br/>
又有了新的發現
</p>
<p>
透過 ExternalInterface 呼叫 window.prompt 時<br/>
完全是同步的<br/>
在瀏覽器對話方塊關閉以前<br/>
Flash Movie 就像是被暫停了一樣
</p>
<span class="fullpost">
<p>
忽然想到 Flash ActionScript 到現在沒有直接提供過全面暫停的功能<br/>
(PS. Flash Player 9 debug 版可以使用 flash.system.System.pause(); 暫停)<br/>
不光是只呼叫 _root.stop(); 那樣<br/>
要連 _root 下面所有子 MovieClip 也一併暫停啊
</p>
<p>
於是更進一步測試<br/>
發現透過 ExternalInterface 呼叫 JavaScript alert, prompt, confirm 時<br/>
能夠將 Flash Player 幾乎全面暫停
</p>
<p>
能夠暫停的項目:
<ol>
<li>MovieClip Timeline</li>
<li>Video play head</li>
<li>Timer, setInterval, setTimeout</li>
<li>for, while 迴圈</li>
<li>影格上的 Stream Sound</li>
</ol>
</p>
<p>
無法暫停的項目:
<ol>
<li>Event Sound, 串流下載播放的 Sound</li>
<li>Network Activity</li>
</ol>
</p>
<p>
這樣一來就很方便了<br/>
除了聲音物件要自行暫停以外<br/>
幾乎大部分 Flash Player 內的活動都能夠用 ExternalInterface 加以暫停
</p>
<p>
而且會比自行實作的更省效能<br/>
因為它連迴圈, Timer 都停住了<br/>
其實已經很接近執行緒 (Threading) 的睡眠 (sleep) 功能
</p>
<p>
聲音播放、網路活動等之所以無法暫停<br/>
原因可能與 Flash Player 內部執行緒配置方式有關<br/>
聲音播放、網路活動都是非同步的<br/>
很可能是在主執行緒之外配置了副執行緒來處理的
</p>
<p>
未來 Flash Player 可能會支援執行緒的功能<br/>
在那之前,就先用這個小技巧<br/>
暫停 Flash Player 主執行緒吧!
</p>
<p>
ActionScript 測試程式:
</p>
<pre name="code" class="as3:showcolumns">
import flash.external.*;
function doPause() {
trace("Before call alert.");
ExternalInterface.call("alert", "Flash Movie 已暫停, 按下確定繼續");
trace("After call alert.");
}
setInterval(function(){trace("onTimer: " + getTimer());}, 1000);
// Ticore's Blog - http://ticore.blogspot.com/
</pre>
<p>
<a target="_blank" href="http://riafiles.googlepages.com/pauseFlash.html">線上測試頁面</a>
</p>
<p>
<a href="http://riafiles.googlepages.com/pauseFlash.zip">測試程式下載</a>
</p>
<p>
相關連結:<br/>
<a href="http://ticore.blogspot.com/2006/12/windowprompt-flash.html">利用 window.prompt 解決 Flash 透明模式下無法輸入中文的問題</a>
</p>
</span>{id: "Ticore"}; //http://www.blogger.com/profile/01433005931305983346noreply@blogger.comtag:blogger.com,1999:blog-6934949377658966040.post-41472390101503548722008-05-28T16:30:00.007+08:002008-07-14T18:14:18.831+08:00Flex - RemoteObject 與 ApplicationDomain 問題<p align="right" class="author"><a href="http://ticore.blogspot.com/">Ticore's Blog</a></p>
<p>
問題出處:<a target="_blank" href="http://mmug.com.tw/forum/viewtopic.php?p=48930">SWFLoader載入問題,當要載入的swf有使用DataServices...</a><br/>
在 Flex App 內,以新的 ApplicationDomain 載入另一個 Flex App 之後<br/>
被讀入的 Flex App 使用 RemoteObject 呼叫會出現問題
</p>
<p>
重新把問題程式碼簡化如下<br/>
因為這問題發生於 HTTP 請求之前,不必配置後端
</p>
<span class="fullpost">
<p>
LoadeeApp.mxml:
</p>
<pre name="code" class="mxml:showcolumns">
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Button label="Submit" click="remoteObj.test(123);"/>
<mx:RemoteObject id="remoteObj" destination="xxx" />
</mx:Application>
</pre>
<p>
LoaderApp.mxml:
</p>
<pre name="code" class="mxml:showcolumns">
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:SWFLoader id="swfLdr" width="100%" height="100%">
<mx:creationComplete>
<![CDATA[
swfLdr.loaderContext = new LoaderContext();
swfLdr.loaderContext.applicationDomain = new ApplicationDomain();
swfLdr.source = "LoadeeApp.swf";
]]>
</mx:creationComplete>
</mx:SWFLoader>
</mx:Application>
</pre>
<p>
編譯之後,執行 LoaderApp,按下按鈕就會得到錯誤訊息
</p>
<pre>
ArgumentError: Error #1063:
Object/http://adobe.com/AS3/2006/builtin::hasOwnProperty()
上的引數個數不相符。需要 0 個,目前為 2 個。
at LoadeeApp/___LoadeeApp_Button1_click()
</pre>
<p>
假如改成 remoteObj.test(); 還會得到堆疊溢位錯誤呢
</p>
<pre>
Error: Error #1023: 發生堆疊溢位。
at Object$/_hasOwnProperty()
at Object/http://adobe.com/AS3/2006/builtin::hasOwnProperty()
at Object$/_hasOwnProperty()
at Object/http://adobe.com/AS3/2006/builtin::hasOwnProperty()
...
</pre>
<p>
從錯誤訊息看起來,其實與 Flex 無關<br/>
問題很可能是出在 Flash ActionScript 3.0 內建 Class 上<br/>
由於 RemoteObject 是繼承 Proxy<br/>
再將問題簡化,剔除 Flex 相關的因素<br/>
僅使用 Flash ActionScript 3.0 以 new ApplicationDomain(); 載入另一個 Flash App<br/>
於被載入的 Flash App 呼叫自訂的 MyProxy 方法
</p>
<p>
LoaderFlash Class:
</p>
<pre name="code" class="as3:showcolumns">
package {
import flash.display.Loader;
import flash.display.Sprite;
import flash.net.URLRequest;
import flash.system.ApplicationDomain;
import flash.system.LoaderContext;
public class LoaderFlash extends Sprite {
protected var ldr:Loader;
protected var ldrCxt:LoaderContext;
protected var req:URLRequest;
public function LoaderFlash() {
ldr = new Loader();
ldrCxt = new LoaderContext(false, new ApplicationDomain());
req = new URLRequest("LoadeeFlash.swf");
ldr.load(req, ldrCxt);
}
}
}
</pre>
<p>
LoadeeFlash Class:
</p>
<pre name="code" class="as3:showcolumns">
package {
import flash.display.Sprite;
public class LoadeeFlash extends Sprite {
public function LoadeeFlash() {
var proxy:MyProxy = new MyProxy();
proxy.test(123);
//proxy.prop++;
}
}
}
</pre>
<p>
MyProxy Class:
</p>
<pre name="code" class="as3:showcolumns">
package {
import flash.utils.Proxy;
import flash.utils.flash_proxy;
public dynamic class MyProxy extends Proxy {
public function MyProxy() {
super();
}
override flash_proxy function callProperty(methodName:*, ... args):* {
trace("callProperty :", methodName, args);
return;
}
override flash_proxy function getProperty(name:*):* {
trace("getProperty :", name);
return;
}
override flash_proxy function hasProperty(name:*):Boolean{
trace("hasProperty :", name);
return true;
}
}
}
</pre>
<p>
執行 LoaderFlash.swf,結果還是會得到一樣的錯誤訊息<br/>
所以 flash.utils.Proxy 無法在 new ApplicationDomain(); 方式載入的 SWF 內使用
</p>
<p>
變通方式,大概只能避免使用到 Proxy 的功能了<br/>
改以 NetConnection 等比較低階的方式使用 Remoting 功能
</p>
<p>
以上的 Bug 至少會發生在以下版本的 Flash Player<br/>
Flash Player 9.0.115.0<br/>
Flash Player 9.0.124.0<br/>
Flash Player 10.0.1.218
</p>
</span>{id: "Ticore"}; //http://www.blogger.com/profile/01433005931305983346noreply@blogger.comtag:blogger.com,1999:blog-6934949377658966040.post-8478749342290403992008-05-23T22:34:00.009+08:002008-07-14T18:24:46.873+08:00Flash Player 10 beta - 新的影格事件<p align="right" class="author"><a href="http://ticore.blogspot.com/">Ticore's Blog</a></p>
<p>
<a target="_blank" href="http://download.macromedia.com/pub/labs/flashplayer10/flashplayer10_as3langref_052008.zip">Flash Player 10 beta 文件</a>出來了<br/>
要觀察新的 API 更方便一些
</p>
<p>
新的 AS3 API 多了兩個影格事件<br/>
分別是 Event.FRAME_CONSTRUCTED, Event.EXIT_FRAME<br/>
看起來有點像 Director 的影格事件<br/>
以往 Flash 從來沒有離開影格的相關事件
</p>
<p>
Event.FRAME_CONSTRUCTED 事件按照文件上所述<br/>
是發生在影格上的 DisplayObject 建立之後<br/>
執行影格程式之前
</p>
<span class="fullpost">
<p>
看起來像是用來補足 Flash Player 9 影格事件的不足<br/>
之前聽到不少人抱怨 AS3 作影格跳躍之後<br/>
無法直接取用該影格的時間軸預置物件 (Timeline-Placed Object)<br/>
必須要等一個影格左右的時間...<br/>
非常不方便!
</p>
<p>
不過新的 frameConstructed 事件也只是將等待一個影格的時間縮短而已<br/>
好像沒有方便到哪去<br/>
至於正式版情況怎樣,就拭目以待了!
</p>
<p>
以下為 Flash Player 10 beta 新影格事件測試程式:<br/>
(需要自行準備一個具有三個影格的空白 fla 文件)
</p>
<pre name="code" class="as3:showcolumns">
package {
import flash.display.*;
import flash.text.*;
import flash.events.*;
public class Main extends MovieClip {
public function Main() {
this.addEventListener(Event.ENTER_FRAME, onEvent);
this.addEventListener(Event.EXIT_FRAME, onEvent);
this.addEventListener(Event.FRAME_CONSTRUCTED, onEvent);
this.addFrameScript(0, onFrame, 1, onFrame, 2, onFrame);
}
private function onFrame():void {
trace(currentFrame, "FrameAction");
}
private function onEvent(evtObj:Event):void {
trace(currentFrame, evtObj.type);
}
}
}
// Ticore's Blog - http://ticore.blogspot.com/
</pre>
<p>
以下是輸出結果:
</p>
<pre>
1 frameConstructed
1 FrameAction
1 exitFrame
2 enterFrame
2 frameConstructed
2 FrameAction
2 exitFrame
3 enterFrame
3 frameConstructed
3 FrameAction
3 exitFrame
1 enterFrame
1 frameConstructed
1 FrameAction
1 exitFrame
..
.
</pre>
<p>
除了第一影格之外,大致上可以看得出來執行順序是<br/>
enterFrame, frameConstructed, FrameAction, exitFrame<br/>
</p>
<p>
相關連結:<br/>
<a href="http://ticore.blogspot.com/2008/05/flash-player-10-beta-mousecursor.html">Flash Player 10 beta - MouseCursor 功能</a><br/>
<a href="http://ticore.blogspot.com/2008/05/flash-player-10-beta-jpegloadercontext.html">Flash Player 10 beta - JPEGLoaderContext 介紹</a><br/>
<a href="http://ticore.blogspot.com/2007/06/flash-9-as3.html">Flash 9 AS3 時間性事件混合測試</a><br/>
<a href="http://ticore.blogspot.com/2007/06/flash-player-8-as2.html">Flash Player 8 AS2 影格程式執行順序</a>
</p>
</span>{id: "Ticore"}; //http://www.blogger.com/profile/01433005931305983346noreply@blogger.comtag:blogger.com,1999:blog-6934949377658966040.post-14561226733626081912008-05-18T15:11:00.009+08:002008-07-14T18:24:20.765+08:00Flash Player 10 beta - MouseCursor 功能<p align="right" class="author"><a href="http://ticore.blogspot.com/">Ticore's Blog</a></p>
<p>
以下介紹 Flash Player 10 beta 新的 Class - MouseCursor<br/>
</p>
<p>
先利用 describeType 觀察 MouseCursor 與 Mouse
</p>
<span class="fullpost">
<pre name="code" class="as3:showcolumns">
import flash.ui.*;
import flash.utils.*;
trace(describeType(MouseCursor));
trace(describeType(Mouse));
</pre>
<p>
可以得到以下輸出結果:
</p>
<pre>
<type name="flash.ui::MouseCursor" base="Class"
isDynamic="true" isFinal="true" isStatic="true">
<extendsClass type="Class"/>
<extendsClass type="Object"/>
<constant name="IBEAM" type="String"/>
<constant name="HAND" type="String"/>
<constant name="BUTTON" type="String"/>
<constant name="AUTO" type="String"/>
<constant name="ARROW" type="String"/>
<accessor name="prototype" access="readonly" type="*" declaredBy="Class"/>
<factory type="flash.ui::MouseCursor">
<extendsClass type="Object"/>
</factory>
</type>
<type name="flash.ui::Mouse" base="Class"
isDynamic="true" isFinal="true" isStatic="true">
<extendsClass type="Class"/>
<extendsClass type="Object"/>
<accessor name="cursor" access="readwrite" type="String" declaredBy="flash.ui::Mouse"/>
<method name="hide" declaredBy="flash.ui::Mouse" returnType="void"/>
<method name="show" declaredBy="flash.ui::Mouse" returnType="void"/>
<accessor name="prototype" access="readonly" type="*" declaredBy="Class"/>
<factory type="flash.ui::Mouse">
<extendsClass type="Object"/>
</factory>
</type>
</pre>
<p>
MouseCursor 內共有五個常數 IBEAM, HAND, BUTTON, AUTO, ARROW<br/>
而剛好 Mouse 多出一個 cursor 屬性<br/>
看起來就像是可以自由決定使用系統鼠標功能
</p>
<p>
實際測試之後,果然如此<br/>
可以自由設定要使用哪一個系統滑鼠游標<br/>
這樣就省事多了,不需要像以前那樣<br/>
要先隱藏系統鼠標,還要再用一個 MovieClip 跟隨滑鼠~~<br/>
</p>
<p>
假如要恢復預設狀態<br/>
只要重新指定為 MouseCursor.AUTO 即可
</p>
<p>
Flex MouseCursor 測試程式:
</p>
<pre name="code" class="mxml:showcolumns">
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="horizontal" backgroundColor="#FFFFFF">
<mx:Script>
<![CDATA[
import flash.ui.Mouse;
]]>
</mx:Script>
<mx:Button label="Auto" buttonMode="true" click="Mouse.cursor = MouseCursor.AUTO;" />
<mx:Button label="Arrow" buttonMode="true" click="Mouse.cursor = MouseCursor.ARROW;" />
<mx:Button label="Hand" buttonMode="true" click="Mouse.cursor = MouseCursor.HAND;" />
<mx:Button label="Button" buttonMode="true" click="Mouse.cursor = MouseCursor.BUTTON;" />
<mx:Button label="IBEAM" buttonMode="true" click="Mouse.cursor = MouseCursor.IBEAM;" />
</mx:Application>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->
</pre>
<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_JHhe1vma7nY/SC_Zone8HII/AAAAAAAAAaA/6U9p5zXsoyc/s1600-h/MouseCursorDemo.gif"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp3.blogger.com/_JHhe1vma7nY/SC_Zone8HII/AAAAAAAAAaA/6U9p5zXsoyc/s320/MouseCursorDemo.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5201615386452958338" /></a>
<p>
相關連結:<br/>
<a href="http://ticore.blogspot.com/2008/05/flash-10-new-frame-events.html">Flash Player 10 beta - 新的影格事件</a><br/>
<a href="http://opensource.adobe.com/wiki/display/flexsdk/Targeting+Flash+Player+10+Beta+with+Flex+SDK+3.0.x">Flex SDK - Targeting Flash Player 10 Beta with Flex SDK 3.0.x</a><br/>
<a href="http://ticore.blogspot.com/2008/05/flash-player-10-beta-jpegloadercontext.html">Flash Player 10 beta - JPEGLoaderContext 介紹</a>
</p>
</span>{id: "Ticore"}; //http://www.blogger.com/profile/01433005931305983346noreply@blogger.comtag:blogger.com,1999:blog-6934949377658966040.post-53225847833720292662008-05-18T12:18:00.012+08:002008-07-14T18:14:19.030+08:00Flash Player 10 beta - JPEGLoaderContext 介紹<p align="right" class="author"><a href="http://ticore.blogspot.com/">Ticore's Blog</a></p>
<p>
最近 Flash Player 10 beta 出了<br/>
各大網站、Blog 已經有太多相關文章了<br/>
在此不再贅述
</p>
<p>
除了那些官方列出來的新功能之外<br/>
還有一些是沒有被發現的<br/>
像是 flash.system::JPEGLoaderContext 類別
</p>
<span class="fullpost">
<p>
先來利用 describeType 觀察一下 JPEGLoaderContext
</p>
<pre name="code" class="as3:showcolumns">
import flash.system.*;
import flash.utils.*;
trace(describeType(JPEGLoaderContext));
</pre>
<p>
可以得到以下輸出結果:
</p>
<pre>
<type name="flash.system::JPEGLoaderContext"
base="Class" isDynamic="true" isFinal="true" isStatic="true">
<extendsClass type="Class"/>
<extendsClass type="Object"/>
<accessor name="prototype" access="readonly" type="*" declaredBy="Class"/>
<factory type="flash.system::JPEGLoaderContext">
<extendsClass type="flash.system::LoaderContext"/>
<extendsClass type="Object"/>
<constructor>
<parameter index="1" type="Number" optional="true"/>
<parameter index="2" type="Boolean" optional="true"/>
<parameter index="3" type="flash.system::ApplicationDomain" optional="true"/>
<parameter index="4" type="flash.system::SecurityDomain" optional="true"/>
</constructor>
<variable name="deblockingFilter" type="Number"/>
<variable name="applicationDomain" type="flash.system::ApplicationDomain"/>
<variable name="securityDomain" type="flash.system::SecurityDomain"/>
<variable name="checkPolicyFile" type="Boolean"/>
</factory>
</type>
</pre>
<p>
從名稱上看起來,用途應該是與 LoaderContext 類似的<br/>
然後是用來處理外部 JPEG 圖檔<br/>
只是多了一個 deblockingFilter 變數<br/>
看起來也很像是去馬賽克用的
</p>
<p>
以下便是實際使用範例:(需要自行準備一個外部圖檔 img.jpg)
</p>
<pre name="code" class="mxml:showcolumns">
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
initialize="init();" layout="horizontal" backgroundColor="#FFFFFF">
<mx:Script>
<![CDATA[
import flash.system.*;
import flash.utils.*;
[Bindable]
public var jpgLdrCxt1:JPEGLoaderContext = new JPEGLoaderContext(0);
public var jpgLdrCxt2:JPEGLoaderContext = new JPEGLoaderContext(1);
public function init():void{
trace(describeType(JPEGLoaderContext));
img1.loaderContext = jpgLdrCxt1;
img1.source = "img.jpg";
img2.loaderContext = jpgLdrCxt2;
img2.source = "img.jpg";
}
]]>
</mx:Script>
<mx:Image id="img1" scaleX="1.5" scaleY="1.5" />
<mx:Image id="img2" scaleX="1.5" scaleY="1.5" />
</mx:Application>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->
</pre>
<p>
以下是實際用 Flash Player 10.0.1.218 執行的效果
</p>
<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_JHhe1vma7nY/SC-y6He8HHI/AAAAAAAAAZ4/847pUOiPvpQ/s1600-h/JPEGLoaderContextDemoPic.jpg"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp1.blogger.com/_JHhe1vma7nY/SC-y6He8HHI/AAAAAAAAAZ4/847pUOiPvpQ/s320/JPEGLoaderContextDemoPic.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5201572806147185778" /></a>
<p>
可以明顯看得出來其中的差異<br/>
deblockingFilter 值大約是在 0-1 之間<br/>
超過 1 以上就沒有太大的差異了<br/>
假如再加上 Bitmap.smoothing 會得到更好的效果
</p>
<p>
相關連結:<br/>
<a href="http://ticore.blogspot.com/2008/05/flash-10-new-frame-events.html">Flash Player 10 beta - 新的影格事件</a><br/>
<a href="http://opensource.adobe.com/wiki/display/flexsdk/Targeting+Flash+Player+10+Beta+with+Flex+SDK+3.0.x">Flex SDK - Targeting Flash Player 10 Beta with Flex SDK 3.0.x</a><br/>
<a href="http://ticore.blogspot.com/2008/05/flash-player-10-beta-mousecursor.html">Flash Player 10 beta - MouseCursor 功能</a>
</p>
</span>{id: "Ticore"}; //http://www.blogger.com/profile/01433005931305983346noreply@blogger.comtag:blogger.com,1999:blog-6934949377658966040.post-4883444616439447672008-05-18T09:24:00.002+08:002008-07-14T18:28:20.495+08:00AIR - ActionScript, JavaScript 混搭技巧<p align="right" class="author"><a href="http://ticore.blogspot.com/">Ticore's Blog</a></p>
<p>
拜 Adobe AIR ActionScript, JavaScript 混搭功能所賜<br/>
ActionScript 3.0 runtime 可以使用 JavaScript 建立的 Function<br/>
也能互相應用 Scope
</p>
<p>
由於 ActionScript 是編譯語言,無法動態建立 Statement, Function<br/>
但是 JavaScript 可以
</p>
<p>
於是想到結合 AIR, JavaScript 動態的功能<br/>
讓 ActionScript 3.0 也能具有直譯程式的能力
</p>
<span class="fullpost">
<p>
以下建立 AS3 物件,動態賦予兩個 JS Function 成員:
</p>
<pre name="code" class="as3:showcolumns">
// Ticore's Blog - http://ticore.blogspot.com/
import flash.utils.*;
import flash.system.*;
var htmlLdr:HTMLLoader = new HTMLLoader();
var jsRuntime:Object = htmlLdr.window;
var obj:Object = {};
obj.name = "Object 1";
obj.getName = new jsRuntime.Function(null, "return this.name;");
obj.setName = new jsRuntime.Function("value", "this.name = value;");
trace(obj.getName()); // Object 1
obj.setName("Object 2");
trace(obj.getName()); // Object 2
</pre>
<p>
相關連結:<br/>
<a href="http://ticore.blogspot.com/2008/05/air-detect-javascript-actionscript.html">AIR - 如何區分 JavaScript 與 ActionScript 物件</a><br/>
<a href="http://ticore.blogspot.com/2008/05/adobe-air-namespace-bug.html">Adobe AIR Namespace Bug</a><br/>
<a href="http://ticore.blogspot.com/2008/05/air-javascript-actionscript-object.html">AIR - JavaScript 與 ActionScript 之間物件的傳遞</a>
</p>
</span>{id: "Ticore"}; //http://www.blogger.com/profile/01433005931305983346noreply@blogger.comtag:blogger.com,1999:blog-6934949377658966040.post-29554495616285473122008-05-17T11:54:00.009+08:002008-07-14T18:28:20.496+08:00AIR - 如何區分 JavaScript 與 ActionScript 物件<p align="right" class="author"><a href="http://ticore.blogspot.com/">Ticore's Blog</a></p>
<p>
Adobe AIR 雖然可以讓 ActionScript 與 JavaScript 物件互相傳遞呼叫<br/>
但是除了基礎物件以外,複雜物件是不會被轉換的<br/>
某些情況下,仍需要注意所持有的物件到底是 AS Object 還是 JS Object<br/>
以下介紹如何區分 JavaScript 與 ActionScript 物件
</p>
<span class="fullpost">
<p>
於 AIR ActionScript runtime 中辨別物件是否為 AS Object
</p>
<pre name="code" class="as3:showcolumns:contentHeight[320px]">
import flash.html.*;
import flash.events.*;
import flash.utils.*;
import flash.system.*;
var htmlLdr:HTMLLoader = new HTMLLoader();
var jsRuntime:Object = htmlLdr.window;
var asObj:Object = new Object();
var asAry:* = new Array();
var asDate:* = new Date();
var asSprite:* = new flash.display.Sprite();
var asXML:* = new XML();
var asXMLList:* = new XMLList();
var asRegExp:* = new RegExp();
var asNS:* = new Namespace();
var asFun:* = function():void{};
var asNo:* = new Number();
var asStr:* = new String();
var asBol:* = new Boolean();
var jsObj:Object = new jsRuntime.Object();
var jsAry:Object = new jsRuntime.Array();
var jsDate:Object = new jsRuntime.Date();
var jsFun:Object = new jsRuntime.Function("", "");
var jsNo:Object = new jsRuntime.Number();
var jsStr:Object = new jsRuntime.String();
var jsBol:Object = new jsRuntime.Boolean();
function isASObject(o:*):Boolean{
//return o.constructor is Class;
return getQualifiedClassName(o).indexOf("flash.html::__HTMLScript") < 0;
}
trace(isASObject(asObj)); // true
trace(isASObject(asAry)); // true
trace(isASObject(asDate)); // true
trace(isASObject(asSprite)); // true
trace(isASObject(asXML)); // true
trace(isASObject(asXMLList)); // true
trace(isASObject(asRegExp)); // true
trace(isASObject(asNS)); // true
trace(isASObject(asFun)); // true
trace(isASObject(asNo)); // true
trace(isASObject(asStr)); // true
trace(isASObject(asBol)); // true
trace(isASObject(jsObj)); // false
trace(isASObject(jsAry)); // false
trace(isASObject(jsDate)); // false
trace(isASObject(jsFun)); // false
trace(isASObject(jsNo)); // true
trace(isASObject(jsStr)); // true
trace(isASObject(jsBol)); // true
// Ticore's Blog - http://ticore.blogspot.com/
</pre>
<p>
於 AIR JavaScript runtime 中辨別物件是否為 JS Object
</p>
<pre name="code" class="js:showcolumns:contentHeight[320px]">
var asObj = new runtime.Object();
var asAry = new runtime.Array();
var asDate = new runtime.Date();
var asSprite = new runtime.flash.display.Sprite();
var asXML = new runtime.XML();
var asXMLList = new runtime.XMLList();
var asRegExp = new runtime.RegExp();
var asFun = runtime.trace;
var asNo = new runtime.Number();
var asStr = new runtime.String();
var asBol = new runtime.Boolean();
var jsObj = new Object();
var jsAry = new Array();
var jsDate = new Date();
var jsFun = function(){};
var jsNo = 10;
var jsStr = "str";
var jsBol = true;
function isJSObject(o) {
return o.constructor instanceof Function;
}
runtime.trace(isJSObject(asObj)); // false
runtime.trace(isJSObject(asAry)); // false
runtime.trace(isJSObject(asDate)); // false
runtime.trace(isJSObject(asSprite)); // false
runtime.trace(isJSObject(asXML)); // false
runtime.trace(isJSObject(asXMLList)); // false
runtime.trace(isJSObject(asRegExp)); // false
runtime.trace(isJSObject(asFun)); // false
runtime.trace(isJSObject(asStr)); // true
runtime.trace(isJSObject(asNo)); // true
runtime.trace(isJSObject(asBol)); // true
runtime.trace(isJSObject(jsObj)); // true
runtime.trace(isJSObject(jsAry)); // true
runtime.trace(isJSObject(jsDate)); // true
runtime.trace(isJSObject(jsFun)); // true
runtime.trace(isJSObject(jsStr)); // true
runtime.trace(isJSObject(jsNo)); // true
runtime.trace(isJSObject(jsBol)); // true
// Ticore's Blog - http://ticore.blogspot.com/
</pre>
<p>
以上的方式,除了 Number, String, Boolean 會自動轉換的物件以外<br/>
應該都可以辨別大部分的 AS or JS Object
</p>
<p>
其實之前嘗試過各種不同的方式<br/>
像是 __proto__, constructor is Class 等等<br/>
但是都無法用在所有的物件判別上
</p>
<p>
相關連結:<br/>
<a href="http://ticore.blogspot.com/2008/05/air-as-js-maskup-skill.html">AIR - ActionScript, JavaScript 混搭技巧</a><br/>
<a href="http://ticore.blogspot.com/2008/05/adobe-air-namespace-bug.html">Adobe AIR Namespace Bug</a><br/>
<a href="http://ticore.blogspot.com/2008/05/air-javascript-actionscript-object.html">AIR - JavaScript 與 ActionScript 之間物件的傳遞</a>
</p>
</span>{id: "Ticore"}; //http://www.blogger.com/profile/01433005931305983346noreply@blogger.comtag:blogger.com,1999:blog-6934949377658966040.post-29896066168339513672008-05-13T19:08:00.003+08:002008-07-14T18:28:20.498+08:00Adobe AIR Namespace Bug<p align="right" class="author"><a href="http://ticore.blogspot.com/">Ticore's Blog</a></p>
<p>
繼續之前的 Adobe AIR AS-JS runtime 混合測試<br/>
發現無法從 JavaScript runtime 建立 AS3 Namespace 實體
</p>
<span class="fullpost">
<p>
AIR JavaScript 測試程式如下:
</p>
<pre name="code" class="js:showcolumns">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
<script type="text/javascript">
new runtime.Namespace();
// Error: Internal Error
new runtime.Namespace("ns", "http://ticore.blogspot.com");
// Error: Internal Error
</script>
</head>
<body>
</body>
</html>
</pre>
<p>
只要嘗試建立 Namespace 就會出現 Error<br/>
於是轉個彎,從 AS3 runtime 建立 Namespace 丟給 JavaScript runtime
</p>
<p>
AIR ActionScript 3.0 測試程式如下:
</p>
<pre name="code" class="as3:showcolumns">
package {
import flash.display.*;
import flash.html.*;
import flash.system.*;
import flash.desktop.*;
public class Main extends MovieClip {
public var htmlLdr:HTMLLoader = new HTMLLoader();
public function Main() {
var nativeApp:NativeApplication = NativeApplication.nativeApplication;
trace("AIR version :", nativeApp.runtimeVersion, nativeApp.runtimePatchLevel);
// AIR version : 1.0.1 4990
trace("Flash Player version :", Capabilities.version);
// Flash Player version : WIN 9,0,124,0
trace("Flash Player type :", Capabilities.playerType);
// Flash Player type : Desktop
// Create javascript function
var jsFun:* = new htmlLdr.window.Function(["obj"], "return obj;");
try {
trace(jsFun(new htmlLdr.window.Object()));
// [object Object]
trace(jsFun(new Object()));
// [object Object]
trace(jsFun(new Namespace("ns", "http://ticore.blogspot.com")));
// AIR runtime crash !
} catch (e:Error) {
trace(e);
}
}
}
}
</pre>
<p>
結果更糟糕,Adobe AIR 直接 Crash!
</p>
<p>
OS:Windows VISTA SP1
</p>
<p>
以上 Bug 至少會發生在以下版本的 Adobe AIR<br/>
Adobe AIR 1.0 4880<br/>
Adobe AIR 1.0.1 4990
</p>
<p>
相關連結:<br/>
<a href="http://ticore.blogspot.com/2008/05/air-as-js-maskup-skill.html">AIR - ActionScript, JavaScript 混搭技巧</a><br/>
<a href="http://ticore.blogspot.com/2008/05/air-detect-javascript-actionscript.html">AIR - 如何區分 JavaScript 與 ActionScript 物件</a><br/>
<a href="http://ticore.blogspot.com/2008/05/air-javascript-actionscript-object.html">AIR - JavaScript 與 ActionScript 之間物件的傳遞</a></p>
</span>{id: "Ticore"}; //http://www.blogger.com/profile/01433005931305983346noreply@blogger.comtag:blogger.com,1999:blog-6934949377658966040.post-40966427533032299452008-05-13T00:19:00.002+08:002008-07-14T18:28:20.499+08:00注意你的 AIR and Flash Player version<p align="right" class="author"><a href="http://ticore.blogspot.com/">Ticore's Blog</a></p>
<p>
自從 Flash Player 進入到 9 版之後,功能越來越複雜<br/>
每一次的 release 都有相當程度變動<br/>
遇到版本更新有關的問題時,只知道自己裝的 Flash Player 是 9 版<br/>
卻不知道是哪一個 build or release<br/>
問題就很難解決了~
</p>
<span class="fullpost">
<p>
Adobe AIR 也是一樣的<br/>
以下便是取得 AIR runtime 與 Flash Player 完整版本的方式
</p>
<pre name="code" class="as3:showcolumns">
// AS3 Get Adobe AIR runtime version
import flash.desktop.*;
var nativeApp:NativeApplication = NativeApplication.nativeApplication;
trace(nativeApp.runtimeVersion); // 1.0
trace(nativeApp.runtimePatchLevel); // 4880
// AS3 Get Flash Player version
trace(flash.system.Capabilities.version); // WIN 9,0,115,0
// AS2 Get Flash Player version
trace(System.capabilities.version); // WIN 9,0,115,0
// AS1 Get Flash Player version
trace($version); // WIN 9,0,115,0
// AS3 Get Operating System
trace(flash.system.Capabilities.os); // Windows XP
// AS2 Get Operating System
trace(System.capabilities.os); // Windows XP
// AS3 Get Flash Player type
trace(flash.system.Capabilities.playerType); // External
// AS2 Get Flash Player type
trace(System.capabilities.playerType); // External
</pre>
</span>{id: "Ticore"}; //http://www.blogger.com/profile/01433005931305983346noreply@blogger.comtag:blogger.com,1999:blog-6934949377658966040.post-28188323678063108282008-05-11T17:36:00.005+08:002008-07-14T18:14:18.865+08:00詭異的 JavaScript typeof 函式<p align="right" class="author"><a href="http://ticore.blogspot.com/">Ticore's Blog</a></p>
<p>
在進行 <a href="http://ticore.blogspot.com/2008/05/air-javascript-actionscript-object.html">AIR AS-JS 測試</a>時,發現 JavaScript typeof 詭異的行為<br/>
對於相同的 Number,使用 new 產生的實體與直接宣告的實體<br/>
使用 typeof 判斷,居然會得到不一樣的型別<br/>
真是太糟糕了
</p>
<span class="fullpost">
<p>
JavaScript typeof 測試程式:
</p>
<pre name="code" class="js:showcolumns">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<pre>
<script type="text/javascript">
document.writeln(typeof(1)); // number
document.writeln(typeof("str")); // string
document.writeln(typeof(true)); // boolean
document.writeln(typeof({})); // object
document.writeln(typeof([])); // object
document.writeln(typeof(function(){})); // function
document.writeln(typeof(new Number(1))); // object
document.writeln(typeof(new String("str"))); // object
document.writeln(typeof(new Boolean(true))); // object
document.writeln(typeof(new Object())); // object
document.writeln(typeof(new Array())); // object
document.writeln(typeof(new Function())); // function
document.writeln(1 == new Number(1)); // true
document.writeln("str" == new String("str")); // true
document.writeln(true == new Boolean(true)); // true
document.writeln(typeof(new Number(1) + 0)); // number
document.writeln(typeof(new Number(1).valueOf())); // number
document.writeln(typeof(new String("str").valueOf())); // string
document.writeln(typeof(new Boolean(true).valueOf())); // boolean
</script>
</pre>
</body>
</html>
</pre>
<p>
假如再多測試一些其它型別,不同的瀏覽器還會得到更多不同的結果呢!
</p>
</span>{id: "Ticore"}; //http://www.blogger.com/profile/01433005931305983346noreply@blogger.comtag:blogger.com,1999:blog-6934949377658966040.post-37152430283163766372008-05-11T15:26:00.011+08:002008-07-14T18:28:20.501+08:00AIR - JavaScript 與 ActionScript 之間物件的傳遞<p align="right" class="author"><a href="http://ticore.blogspot.com/">Ticore's Blog</a></p>
<p>
Adobe AIR 執行環境下,整合了 ActionScript 3.0 與 JavaScript<br/>
可以在 ActionScript runtime 下,呼叫 JavaScript function;反之亦然<br/>
在 AIR HTML App 下,許多延伸功能,像是 SQLite, File System....<br/>
JavaScript 也都是透過呼叫 ActionScript 達到的<br/>
而 JavaScript 甚至可以直接透過 Script 標籤引用外部 AS Library
</p>
<span class="fullpost">
<p>
但是,AIR AS-JS 真的整合那麼好嗎?<br/>
以下先就物件在 AS 與 JS runtime 之間傳遞與轉型測試<br/>
分別在 AIR AS, JS 執行環境下產生 AS, JS 常用物件實體<br/>
測試物件的型別
</p>
<p>AIR ActionScript 3.0 測試程式:</p>
<pre name="code" class="as3:showcolumns">
import flash.html.*;
var htmlLdr:HTMLLoader = new HTMLLoader();
var jsRuntime:Object = htmlLdr.window;
function traceType(obj) {
trace(flash.utils.getQualifiedClassName(obj));
}
traceType(new jsRuntime.Object()); // flash.html::__HTMLScriptObject
traceType(new jsRuntime.Array()); // flash.html::__HTMLScriptArray
traceType(new jsRuntime.Date()); // flash.html::__HTMLScriptObject
traceType(new jsRuntime.Function()); // flash.html::__HTMLScriptFunction
traceType(new jsRuntime.RegExp()); // flash.html::__HTMLScriptObject
traceType(new jsRuntime.String()); // String
traceType(new jsRuntime.Number()); // int
traceType(new jsRuntime.Boolean()); // Boolean
traceType(new Object()); // Object
traceType(new Array()); // Array
traceType(new Date()); // Date
traceType(new Function()); // Function-35
traceType(new RegExp()); // RegExp
traceType(new String()); // String
traceType(new Number()); // int
traceType(new int()); // int
traceType(new uint()); // int
traceType(new Boolean()); // Boolean
traceType(1.1); // Number
traceType(true); // Boolean
traceType("str"); // String
</pre>
<p>AIR JavaScript 測試程式:</p>
<pre name="code" class="js:showcolumns">
function traceType(obj) {
runtime.trace(runtime.flash.utils.getQualifiedClassName(obj));
}
traceType(new Object()); // flash.html::__HTMLScriptObject
traceType(new Array()); // flash.html::__HTMLScriptArray
traceType(new Date()); // flash.html::__HTMLScriptObject
traceType(new Function()); // flash.html::__HTMLScriptFunction
traceType(new RegExp()); // flash.html::__HTMLScriptObject
traceType(new String()); // String
traceType(new Number()); // int
traceType(new Boolean()); // Boolean
traceType(new runtime.Object()); // Array
traceType(new runtime.Array()); // Array
traceType(new runtime.Date()); // Date
traceType(new runtime.Function()); // Function-35
traceType(new runtime.RegExp()); // RegExp
traceType(new runtime.String()); // Boolean
traceType(new runtime.Number()); // int
traceType(new runtime.int()); // int
traceType(new runtime.uint()); // int
traceType(new runtime.Boolean()); // Boolean
traceType(1.1); // Number
traceType(true); // Boolean
traceType("str"); // String
</pre>
<p>
從測試結果看起來,似乎只有 Number, Boolean, String 可能是共用的型別<br/>
或者是在 AS-JS 傳遞時,被自動轉換了<br/>
至於其它複雜型別的物件,可能是被包覆為 Proxy 物件<br/>
假如真的是如此,複雜物件在 AS-JS 傳遞時必須要額外注意了<br/>
</p>
<p>
可能會發現到以上的測試都只有使用 AS3 getQualifiedClassName 觀察型別<br/>
沒有用到 JS typeof 測試<br/>
原因是 typeof 功能實在太陽春而且詭異,無法用來測試<br/>
參考 <a href="http://ticore.blogspot.com/2008/05/javascript-typeof-oddity.html">詭異的 JavaScript typeof 函式</a>
</p>
<p>
相關連結:<br/>
<a href="http://ticore.blogspot.com/2008/05/air-as-js-maskup-skill.html">AIR - ActionScript, JavaScript 混搭技巧</a><br/>
<a href="http://ticore.blogspot.com/2008/05/air-detect-javascript-actionscript.html">AIR - 如何區分 JavaScript 與 ActionScript 物件</a><br/>
<a href="http://ticore.blogspot.com/2008/05/adobe-air-namespace-bug.html">Adobe AIR Namespace Bug</a>
</p>
</span>