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 &lt; (width + 1) * magniFactor || bmpData.height &lt; (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"> &lt;?xml version="1.0" encoding="utf-8"?&gt; &lt;mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" verticalAlign="middle" backgroundColor="#FFFFFF" creationComplete="init();" fontSize="12"&gt; &lt;mx:Script&gt; &lt;![CDATA[ public var comp:BindingComp; public function init():void{ comp = new BindingComp(); comp.initialize(); } ]]&gt; &lt;/mx:Script&gt; &lt;mx:HBox&gt; &lt;mx:Label text="No 1:" /&gt; &lt;mx:NumericStepper id="no1" maximum="100" /&gt; &lt;/mx:HBox&gt; &lt;mx:HBox&gt; &lt;mx:Label text="No 2:" /&gt; &lt;mx:NumericStepper id="no2" maximum="100" /&gt; &lt;/mx:HBox&gt; &lt;mx:CheckBox id="chk" label="DataBinding Enabled" change="comp.target = chk.selected ? this : null;" /&gt; &lt;/mx:Application&gt; &lt;!-- Ticore's Blog - http://ticore.blogspot.com/ --&gt; </pre> <p> BindingComp.mxml: </p> <pre name="code" class="mxml:showcolumns"> &lt;?xml version="1.0" encoding="utf-8"?&gt; &lt;mx:UIComponent xmlns:mx="http://www.adobe.com/2006/mxml"&gt; &lt;mx:Script&gt; &lt;![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; } ]]&gt; &lt;/mx:Script&gt; &lt;mx:Model&gt; {doBinding1(target.no1.value)} &lt;/mx:Model&gt; &lt;mx:Model&gt; {doBinding2(target.no2.value)} &lt;/mx:Model&gt; &lt;/mx:UIComponent&gt; &lt;!-- Ticore's Blog - http://ticore.blogspot.com/ --&gt; </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]"> &lt;?xml version="1.0"?&gt; &lt;mx:Application layout="vertical" fontSize="12" backgroundColor="#FFFFFF" xmlns:mx="http://www.adobe.com/2006/mxml"&gt; &lt;mx:Style&gt; HBox.whiteBox { paddingTop: 15px; paddingBottom: 15px; paddingLeft: 15px; paddingRight: 15px; backgroundColor: #000000; } &lt;/mx:Style&gt; &lt;mx:HBox styleName="whiteBox" alpha="{alphaSlider.value}" blendMode="{blendModeCb.value ? blendModeCb.value : 'normal'}"&gt; &lt;mx:HBox styleName="whiteBox"&gt; &lt;mx:HBox styleName="whiteBox"&gt; &lt;mx:HBox styleName="whiteBox" /&gt; &lt;/mx:HBox&gt; &lt;/mx:HBox&gt; &lt;/mx:HBox&gt; &lt;mx:HRule width="100%" /&gt; &lt;mx:HBox verticalAlign="middle"&gt; &lt;mx:Label text="BlendMode: " /&gt; &lt;mx:ComboBox id="blendModeCb"&gt; &lt;mx:dataProvider&gt; ["normal", "layer", "darken", "invert", "hardlight"] &lt;/mx:dataProvider&gt; &lt;/mx:ComboBox&gt; &lt;/mx:HBox&gt; &lt;mx:HBox verticalAlign="middle"&gt; &lt;mx:Label text="Alpha: " /&gt; &lt;mx:HSlider id="alphaSlider" value="0.5" tickValues="[0, 0.5, 1]" labels="[0, 0.5, 1]" minimum="0" maximum="1" liveDragging="true" /&gt; &lt;/mx:HBox&gt; &lt;/mx:Application&gt; &lt;!-- Ticore's Blog - http://ticore.blogspot.com/ --&gt; </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"> &lt;?xml version="1.0" encoding="utf-8"?&gt; &lt;mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" backgroundColor="#FFFFFF" layout="vertical" fontSize="12"&gt; &lt;mx:Label text="Binding Source:" /&gt; &lt;mx:HSlider id="slider1" snapInterval="1" maximum="100" value="50" /&gt; &lt;mx:Label text="Binding Destination:" /&gt; &lt;mx:HSlider id="slider2" snapInterval="1" maximum="100" value="{slider1.value}" /&gt; &lt;/mx:Application&gt; &lt;!-- Ticore's Blog - http://ticore.blogspot.com/ --&gt; </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]"> &lt;?xml version="1.0" encoding="utf-8"?&gt; &lt;mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" backgroundColor="#FFFFFF" layout="vertical" fontSize="12" implements="mx.binding.IBindingClient" creationComplete="onCreateComplete();"&gt; &lt;mx:Script&gt; &lt;![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"); } ]]&gt; &lt;/mx:Script&gt; &lt;mx:Label text="Binding Source:" /&gt; &lt;mx:HSlider id="slider1" snapInterval="1" maximum="100" value="50" /&gt; &lt;mx:Label text="Binding Destination:" /&gt; &lt;mx:HSlider id="slider2" snapInterval="1" maximum="100" /&gt; &lt;/mx:Application&gt; &lt;!-- Ticore's Blog - http://ticore.blogspot.com/ --&gt; </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"> &lt;?xml version="1.0" encoding="utf-8"?&gt; &lt;mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" backgroundColor="#FFFFFF" layout="vertical" fontSize="12" creationComplete="onCreateComplete();"&gt; &lt;mx:Script&gt; &lt;![CDATA[ import mx.binding.*; public function onCreateComplete():void{ BindingManager.debugBinding("slider2.value"); } ]]&gt; &lt;/mx:Script&gt; &lt;mx:Label text="Binding Source:" /&gt; &lt;mx:HSlider id="slider1" snapInterval="1" maximum="100" value="50" /&gt; &lt;mx:Label text="Binding Destination:" /&gt; &lt;mx:HSlider id="slider2" snapInterval="1" maximum="100" value="{slider1.value}" /&gt; &lt;mx:CheckBox id="chk" label="Binding Enabled" selected="true" change="BindingManager.setEnabled(this, chk.selected); btn.enabled = chk.selected;" /&gt; &lt;mx:Button id="btn" label="Execute DataBinding" click="BindingManager.executeBindings(this, 'slider2.value', null);" /&gt; &lt;/mx:Application&gt; &lt;!-- Ticore's Blog - http://ticore.blogspot.com/ --&gt; </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"> &lt;mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" backgroundColor="#FFFFFF" layout="vertical" fontSize="12"&gt; &lt;mx:Label text="Binding Source:" /&gt; &lt;mx:HSlider id="slider1" snapInterval="1" maximum="100" /&gt; &lt;mx:Label text="Binding Destination:" /&gt; &lt;mx:HSlider id="slider2" snapInterval="1" maximum="100" value="{trace('Before :', slider2.value), setTimeout(function():void{trace('After :', slider2.value);}, 0), slider1.value}"/&gt; &lt;/mx:Application&gt; &lt;!-- Ticore's Blog - http://ticore.blogspot.com/ --&gt; </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"> &lt;?xml version="1.0" encoding="utf-8"?&gt; &lt;mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"&gt; &lt;mx:Button label="Submit" click="remoteObj.test(123);"/&gt; &lt;mx:RemoteObject id="remoteObj" destination="xxx" /&gt; &lt;/mx:Application&gt; </pre> <p> LoaderApp.mxml: </p> <pre name="code" class="mxml:showcolumns"> &lt;?xml version="1.0" encoding="utf-8"?&gt; &lt;mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"&gt; &lt;mx:SWFLoader id="swfLdr" width="100%" height="100%"&gt; &lt;mx:creationComplete&gt; &lt;![CDATA[ swfLdr.loaderContext = new LoaderContext(); swfLdr.loaderContext.applicationDomain = new ApplicationDomain(); swfLdr.source = "LoadeeApp.swf"; ]]&gt; &lt;/mx:creationComplete&gt; &lt;/mx:SWFLoader&gt; &lt;/mx:Application&gt; </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> &lt;type name="flash.ui::MouseCursor" base="Class" isDynamic="true" isFinal="true" isStatic="true"&gt; &lt;extendsClass type="Class"/&gt; &lt;extendsClass type="Object"/&gt; &lt;constant name="IBEAM" type="String"/&gt; &lt;constant name="HAND" type="String"/&gt; &lt;constant name="BUTTON" type="String"/&gt; &lt;constant name="AUTO" type="String"/&gt; &lt;constant name="ARROW" type="String"/&gt; &lt;accessor name="prototype" access="readonly" type="*" declaredBy="Class"/&gt; &lt;factory type="flash.ui::MouseCursor"&gt; &lt;extendsClass type="Object"/&gt; &lt;/factory&gt; &lt;/type&gt; &lt;type name="flash.ui::Mouse" base="Class" isDynamic="true" isFinal="true" isStatic="true"&gt; &lt;extendsClass type="Class"/&gt; &lt;extendsClass type="Object"/&gt; &lt;accessor name="cursor" access="readwrite" type="String" declaredBy="flash.ui::Mouse"/&gt; &lt;method name="hide" declaredBy="flash.ui::Mouse" returnType="void"/&gt; &lt;method name="show" declaredBy="flash.ui::Mouse" returnType="void"/&gt; &lt;accessor name="prototype" access="readonly" type="*" declaredBy="Class"/&gt; &lt;factory type="flash.ui::Mouse"&gt; &lt;extendsClass type="Object"/&gt; &lt;/factory&gt; &lt;/type&gt; </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"> &lt;?xml version="1.0" encoding="utf-8"?&gt; &lt;mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="horizontal" backgroundColor="#FFFFFF"&gt; &lt;mx:Script&gt; &lt;![CDATA[ import flash.ui.Mouse; ]]&gt; &lt;/mx:Script&gt; &lt;mx:Button label="Auto" buttonMode="true" click="Mouse.cursor = MouseCursor.AUTO;" /&gt; &lt;mx:Button label="Arrow" buttonMode="true" click="Mouse.cursor = MouseCursor.ARROW;" /&gt; &lt;mx:Button label="Hand" buttonMode="true" click="Mouse.cursor = MouseCursor.HAND;" /&gt; &lt;mx:Button label="Button" buttonMode="true" click="Mouse.cursor = MouseCursor.BUTTON;" /&gt; &lt;mx:Button label="IBEAM" buttonMode="true" click="Mouse.cursor = MouseCursor.IBEAM;" /&gt; &lt;/mx:Application&gt; &lt;!-- Ticore's Blog - http://ticore.blogspot.com/ --&gt; </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> &lt;type name="flash.system::JPEGLoaderContext" base="Class" isDynamic="true" isFinal="true" isStatic="true"&gt; &lt;extendsClass type="Class"/&gt; &lt;extendsClass type="Object"/&gt; &lt;accessor name="prototype" access="readonly" type="*" declaredBy="Class"/&gt; &lt;factory type="flash.system::JPEGLoaderContext"&gt; &lt;extendsClass type="flash.system::LoaderContext"/&gt; &lt;extendsClass type="Object"/&gt; &lt;constructor&gt; &lt;parameter index="1" type="Number" optional="true"/&gt; &lt;parameter index="2" type="Boolean" optional="true"/&gt; &lt;parameter index="3" type="flash.system::ApplicationDomain" optional="true"/&gt; &lt;parameter index="4" type="flash.system::SecurityDomain" optional="true"/&gt; &lt;/constructor&gt; &lt;variable name="deblockingFilter" type="Number"/&gt; &lt;variable name="applicationDomain" type="flash.system::ApplicationDomain"/&gt; &lt;variable name="securityDomain" type="flash.system::SecurityDomain"/&gt; &lt;variable name="checkPolicyFile" type="Boolean"/&gt; &lt;/factory&gt; &lt;/type&gt; </pre> <p> 從名稱上看起來,用途應該是與 LoaderContext 類似的<br/> 然後是用來處理外部 JPEG 圖檔<br/> 只是多了一個 deblockingFilter 變數<br/> 看起來也很像是去馬賽克用的 </p> <p> 以下便是實際使用範例:(需要自行準備一個外部圖檔 img.jpg) </p> <pre name="code" class="mxml:showcolumns"> &lt;?xml version="1.0" encoding="utf-8"?&gt; &lt;mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" initialize="init();" layout="horizontal" backgroundColor="#FFFFFF"&gt; &lt;mx:Script&gt; &lt;![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"; } ]]&gt; &lt;/mx:Script&gt; &lt;mx:Image id="img1" scaleX="1.5" scaleY="1.5" /&gt; &lt;mx:Image id="img2" scaleX="1.5" scaleY="1.5" /&gt; &lt;/mx:Application&gt; &lt;!-- Ticore's Blog - http://ticore.blogspot.com/ --&gt; </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") &lt; 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"> &lt;html&gt; &lt;head&gt; &lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8" /&gt; &lt;title&gt;&lt;/title&gt; &lt;script type="text/javascript"&gt; new runtime.Namespace(); // Error: Internal Error new runtime.Namespace("ns", "http://ticore.blogspot.com"); // Error: Internal Error &lt;/script&gt; &lt;/head&gt; &lt;body&gt; &lt;/body&gt; &lt;/html&gt; </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"> &lt;html&gt; &lt;head&gt; &lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8" /&gt; &lt;/head&gt; &lt;body&gt; &lt;pre&gt; &lt;script type="text/javascript"&gt; 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 &lt;/script&gt; &lt;/pre&gt; &lt;/body&gt; &lt;/html&gt; </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>