2008年5月31日星期六

Flash 技巧 - 利用 ExternalInterface 完全暫停 Flash Movie 程序   [+/-]

Ticore's Blog

最近在 review 一年半以前發現的技巧時
『利用 window.prompt 解決 Flash 透明模式下無法輸入中文的問題』
又有了新的發現

透過 ExternalInterface 呼叫 window.prompt 時
完全是同步的
在瀏覽器對話方塊關閉以前
Flash Movie 就像是被暫停了一樣

忽然想到 Flash ActionScript 到現在沒有直接提供過全面暫停的功能
(PS. Flash Player 9 debug 版可以使用 flash.system.System.pause(); 暫停)
不光是只呼叫 _root.stop(); 那樣
要連 _root 下面所有子 MovieClip 也一併暫停啊

於是更進一步測試
發現透過 ExternalInterface 呼叫 JavaScript alert, prompt, confirm 時
能夠將 Flash Player 幾乎全面暫停

能夠暫停的項目:

  1. MovieClip Timeline
  2. Video play head
  3. Timer, setInterval, setTimeout
  4. for, while 迴圈
  5. 影格上的 Stream Sound

無法暫停的項目:

  1. Event Sound, 串流下載播放的 Sound
  2. Network Activity

這樣一來就很方便了
除了聲音物件要自行暫停以外
幾乎大部分 Flash Player 內的活動都能夠用 ExternalInterface 加以暫停

而且會比自行實作的更省效能
因為它連迴圈, Timer 都停住了
其實已經很接近執行緒 (Threading) 的睡眠 (sleep) 功能

聲音播放、網路活動等之所以無法暫停
原因可能與 Flash Player 內部執行緒配置方式有關
聲音播放、網路活動都是非同步的
很可能是在主執行緒之外配置了副執行緒來處理的

未來 Flash Player 可能會支援執行緒的功能
在那之前,就先用這個小技巧
暫停 Flash Player 主執行緒吧!

ActionScript 測試程式:

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/

線上測試頁面

測試程式下載

相關連結:
利用 window.prompt 解決 Flash 透明模式下無法輸入中文的問題

PS. 上述功能主要是以 AS2.0 測試的
後來邦邦告知可能會引發 Script Timeout 問題
測試之後發現 AS3.0 上執行類似的動作
只要 JS Alert, Prompt 對話方塊超過預設 15 秒沒有關閉
便會引發 Script Timeout 問題

Read more...

2008年5月28日星期三

Flex - RemoteObject 與 ApplicationDomain 問題   [+/-]

Ticore's Blog

問題出處:SWFLoader載入問題,當要載入的swf有使用DataServices...
在 Flex App 內,以新的 ApplicationDomain 載入另一個 Flex App 之後
被讀入的 Flex App 使用 RemoteObject 呼叫會出現問題

重新把問題程式碼簡化如下
因為這問題發生於 HTTP 請求之前,不必配置後端

LoadeeApp.mxml:

<?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>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->

LoaderApp.mxml:

<?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>
<!-- Ticore's Blog - http://ticore.blogspot.com/ -->

編譯之後,執行 LoaderApp,按下按鈕就會得到錯誤訊息

ArgumentError: Error #1063:
 Object/http://adobe.com/AS3/2006/builtin::hasOwnProperty()
 上的引數個數不相符。需要 0 個,目前為 2 個。
 at LoadeeApp/___LoadeeApp_Button1_click()

假如改成 remoteObj.test(); 還會得到堆疊溢位錯誤呢

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()
 ...

從錯誤訊息看起來,其實與 Flex 無關
問題很可能是出在 Flash ActionScript 3.0 內建 Class 上
由於 RemoteObject 是繼承 Proxy
再將問題簡化,剔除 Flex 相關的因素
僅使用 Flash ActionScript 3.0 以 new ApplicationDomain(); 載入另一個 Flash App
於被載入的 Flash App 呼叫自訂的 MyProxy 方法

LoaderFlash Class:

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);
  }
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

LoadeeFlash Class:

package {
 import flash.display.Sprite;

 public class LoadeeFlash extends Sprite {
  public function LoadeeFlash() {
   var proxy:MyProxy = new MyProxy();
   proxy.test(123);
   //proxy.prop++;
  }
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

MyProxy Class:

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;
  }
 }
}
// Ticore's Blog - http://ticore.blogspot.com/

下載測試程式碼

執行 LoaderFlash.swf,結果還是會得到一樣的錯誤訊息
所以 flash.utils.Proxy 無法在 new ApplicationDomain(); 方式載入的 SWF 內使用

變通方式,大概只能避免使用到 Proxy 的功能了
改以 NetConnection 等比較低階的方式使用 Remoting 功能

以上的 Bug 至少會發生在以下版本的 Flash Player
Flash Player 9.0.115.0
Flash Player 9.0.124.0
Flash Player 10.0.0.525
Flash Player 10.0.1.218
Flash Player 10.0.12.10
Flash Player 10.0.12.29
Flash Player 10.0.12.36
Flash Player 10.0.22.87

Read more...

2008年5月23日星期五

Flash Player 10 beta - 新的影格事件   [+/-]

Ticore's Blog

Flash Player 10 beta 文件出來了
要觀察新的 API 更方便一些

新的 AS3 API 多了兩個影格事件
分別是 Event.FRAME_CONSTRUCTED, Event.EXIT_FRAME
看起來有點像 Director 的影格事件
以往 Flash 從來沒有離開影格的相關事件

Event.FRAME_CONSTRUCTED 事件按照文件上所述
是發生在影格上的 DisplayObject 建立之後
執行影格程式之前

看起來像是用來補足 Flash Player 9 影格事件的不足
之前聽到不少人抱怨 AS3 作影格跳躍之後
無法直接取用該影格的時間軸預置物件 (Timeline-Placed Object)
必須要等一個影格左右的時間...
非常不方便!

不過新的 frameConstructed 事件也只是將等待一個影格的時間縮短而已
好像沒有方便到哪去
至於正式版情況怎樣,就拭目以待了!

以下為 Flash Player 10 beta 新影格事件測試程式:
(需要自行準備一個具有三個影格的空白 fla 文件)

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/

以下是輸出結果:

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
..
.

除了第一影格之外,大致上可以看得出來執行順序是
enterFrame, frameConstructed, FrameAction, exitFrame

相關連結:
Flash Player 10 beta - MouseCursor 功能
Flash Player 10 beta - JPEGLoaderContext 介紹
Flash 9 AS3 時間性事件混合測試
Flash Player 8 AS2 影格程式執行順序

Read more...

2008年5月18日星期日

Flash Player 10 beta - MouseCursor 功能   [+/-]

Ticore's Blog

以下介紹 Flash Player 10 beta 新的 Class - MouseCursor

先利用 describeType 觀察 MouseCursor 與 Mouse

import flash.ui.*;
import flash.utils.*;

trace(describeType(MouseCursor));
trace(describeType(Mouse));

可以得到以下輸出結果:

<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>

MouseCursor 內共有五個常數 IBEAM, HAND, BUTTON, AUTO, ARROW
而剛好 Mouse 多出一個 cursor 屬性
看起來就像是可以自由決定使用系統鼠標功能

實際測試之後,果然如此
可以自由設定要使用哪一個系統滑鼠游標
這樣就省事多了,不需要像以前那樣
要先隱藏系統鼠標,還要再用一個 MovieClip 跟隨滑鼠~~

假如要恢復預設狀態
只要重新指定為 MouseCursor.AUTO 即可

Flex MouseCursor 測試程式:

<?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/ -->

相關連結:
Flash Player 10 beta - 新的影格事件
Flex SDK - Targeting Flash Player 10 Beta with Flex SDK 3.0.x
Flash Player 10 beta - JPEGLoaderContext 介紹

Read more...

Flash Player 10 beta - JPEGLoaderContext 介紹   [+/-]

Ticore's Blog

最近 Flash Player 10 beta 出了
各大網站、Blog 已經有太多相關文章了
在此不再贅述

除了那些官方列出來的新功能之外
還有一些是沒有被發現的
像是 flash.system::JPEGLoaderContext 類別

先來利用 describeType 觀察一下 JPEGLoaderContext

import flash.system.*;
import flash.utils.*;
trace(describeType(JPEGLoaderContext));

可以得到以下輸出結果:

<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>

從名稱上看起來,用途應該是與 LoaderContext 類似的
然後是用來處理外部 JPEG 圖檔
只是多了一個 deblockingFilter 變數
看起來也很像是去馬賽克用的

以下便是實際使用範例:(需要自行準備一個外部圖檔 img.jpg)

<?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/ -->

以下是實際用 Flash Player 10.0.1.218 執行的效果

可以明顯看得出來其中的差異
deblockingFilter 值大約是在 0-1 之間
超過 1 以上就沒有太大的差異了
假如再加上 Bitmap.smoothing 會得到更好的效果

相關連結:
Flash Player 10 beta - 新的影格事件
Flex SDK - Targeting Flash Player 10 Beta with Flex SDK 3.0.x
Flash Player 10 beta - MouseCursor 功能

Read more...

AIR - ActionScript, JavaScript 混搭技巧   [+/-]

Ticore's Blog

拜 Adobe AIR ActionScript, JavaScript 混搭功能所賜
ActionScript 3.0 runtime 可以使用 JavaScript 建立的 Function
也能互相應用 Scope

由於 ActionScript 是編譯語言,無法動態建立 Statement, Function
但是 JavaScript 可以

於是想到結合 AIR, JavaScript 動態的功能
讓 ActionScript 3.0 也能具有直譯程式的能力

以下建立 AS3 物件,動態賦予兩個 JS Function 成員:

// 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

相關連結:
AIR - 詭異的類別物件比較結果
AIR JavaScript Runtime 的物件型別
Adobe AIR 混搭測試
純程式建立 AIR AS3-JS 混搭的簡單範例
AIR - 如何區分 JavaScript 與 ActionScript 物件
Adobe AIR Namespace Bug
AIR - JavaScript 與 ActionScript 之間物件的傳遞

Read more...

2008年5月17日星期六

AIR - 如何區分 JavaScript 與 ActionScript 物件   [+/-]

Ticore's Blog

Adobe AIR 雖然可以讓 ActionScript 與 JavaScript 物件互相傳遞呼叫
但是除了基礎物件以外,複雜物件是不會被轉換的
某些情況下,仍需要注意所持有的物件到底是 AS Object 還是 JS Object
以下介紹如何區分 JavaScript 與 ActionScript 物件

於 AIR ActionScript runtime 中辨別物件是否為 AS Object

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/

於 AIR JavaScript runtime 中辨別物件是否為 JS Object


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/

以上的方式,除了 Number, String, Boolean 會自動轉換的物件以外
應該都可以辨別大部分的 AS or JS Object

其實之前嘗試過各種不同的方式
像是 __proto__, constructor is Class 等等
但是都無法用在所有的物件判別上

相關連結:
AIR - 詭異的類別物件比較結果
AIR JavaScript Runtime 的物件型別
Adobe AIR 混搭測試
純程式建立 AIR AS3-JS 混搭的簡單範例
AIR - ActionScript, JavaScript 混搭技巧
Adobe AIR Namespace Bug
AIR - JavaScript 與 ActionScript 之間物件的傳遞

Read more...

2008年5月13日星期二

Adobe AIR Namespace Bug   [+/-]

Ticore's Blog

繼續之前的 Adobe AIR AS-JS runtime 混合測試
發現無法從 JavaScript runtime 建立 AS3 Namespace 實體

AIR JavaScript 測試程式如下:

<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>

只要嘗試建立 Namespace 就會出現 Error
於是轉個彎,從 AS3 runtime 建立 Namespace 丟給 JavaScript runtime

AIR ActionScript 3.0 測試程式如下:

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);
   }
  }
 }
}

結果更糟糕,Adobe AIR 直接 Crash!

以上 Bug 至少會發生在以下版本的 Adobe AIR
Adobe AIR 1.0.0.4880 win
Adobe AIR 1.0.1.4990 win
Adobe AIR 1.1.0.5790 win
Adobe AIR 1.5.0.7220 win
Adobe AIR 1.5.1.8210 win

相關連結:
AIR - 詭異的類別物件比較結果
AIR JavaScript Runtime 的物件型別
Adobe AIR 混搭測試
純程式建立 AIR AS3-JS 混搭的簡單範例
AIR - ActionScript, JavaScript 混搭技巧
AIR - 如何區分 JavaScript 與 ActionScript 物件
AIR - JavaScript 與 ActionScript 之間物件的傳遞

Read more...

注意你的 AIR and Flash Player version   [+/-]

Ticore's Blog

自從 Flash Player 進入到 9 版之後,功能越來越複雜
每一次的 release 都有相當程度變動
遇到版本更新有關的問題時,只知道自己裝的 Flash Player 是 9 版
卻不知道是哪一個 build or release
問題就很難解決了~

Adobe AIR 也是一樣的
以下便是取得 AIR runtime 與 Flash Player 完整版本的方式

// 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

// Ticore's Blog - http://ticore.blogspot.com/

相關連結:
AIR - 詭異的類別物件比較結果
AIR JavaScript Runtime 的物件型別
Adobe AIR 混搭測試
純程式建立 AIR AS3-JS 混搭的簡單範例
AIR - ActionScript, JavaScript 混搭技巧
AIR - JavaScript 與 ActionScript 之間物件的傳遞
AIR - 如何區分 JavaScript 與 ActionScript 物件
Adobe AIR Namespace Bug

Read more...

2008年5月11日星期日

詭異的 JavaScript typeof 函式   [+/-]

Ticore's Blog

在進行 AIR AS-JS 測試時,發現 JavaScript typeof 詭異的行為
對於相同的 Number,使用 new 產生的實體與直接宣告的實體
使用 typeof 判斷,居然會得到不一樣的型別
真是太糟糕了

JavaScript typeof 測試程式:

<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>

假如再多測試一些其它型別,不同的瀏覽器還會得到更多不同的結果呢!

Read more...

AIR - JavaScript 與 ActionScript 之間物件的傳遞   [+/-]

Ticore's Blog

Adobe AIR 執行環境下,整合了 ActionScript 3.0 與 JavaScript
可以在 ActionScript runtime 下,呼叫 JavaScript function;反之亦然
在 AIR HTML App 下,許多延伸功能,像是 SQLite, File System....
JavaScript 也都是透過呼叫 ActionScript 達到的
而 JavaScript 甚至可以直接透過 Script 標籤引用外部 AS Library

但是,AIR AS-JS 真的整合那麼好嗎?
以下先就物件在 AS 與 JS runtime 之間傳遞與轉型測試
分別在 AIR AS, JS 執行環境下產生 AS, JS 常用物件實體
測試物件的型別

AIR ActionScript 3.0 測試程式:

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

AIR JavaScript 測試程式:

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

從測試結果看起來,似乎只有 Number, Boolean, String 可能是共用的型別
或者是在 AS-JS 傳遞時,被自動轉換了
至於其它複雜型別的物件,可能是被包覆為 Proxy 物件
假如真的是如此,複雜物件在 AS-JS 傳遞時必須要額外注意了

可能會發現到以上的測試都只有使用 AS3 getQualifiedClassName 觀察型別
沒有用到 JS typeof 測試
原因是 typeof 功能實在太陽春而且詭異,無法用來測試
參考 詭異的 JavaScript typeof 函式

相關連結:
AIR - 詭異的類別物件比較結果
AIR JavaScript Runtime 的物件型別
Adobe AIR 混搭測試
純程式建立 AIR AS3-JS 混搭的簡單範例
AIR - ActionScript, JavaScript 混搭技巧
AIR - 如何區分 JavaScript 與 ActionScript 物件
Adobe AIR Namespace Bug

Read more...

2008年5月4日星期日

一行 AS3 程式讓 Flash Player 9 死機 Part 4   [+/-]

Ticore's Blog

Bug 又來了,以下任一行 AS3 程式都會造成 Flash Player Crash

Object['isPrototypeOf']();
Object['hasOwnProperty']();
Object['propertyIsEnumerable']();
Object['setPropertyIsEnumerable']();

// Ticore's Blog - http://ticore.blogspot.com/

實在是太詭異了,這麼平常的 Class - Object
居然可以輕易讓 Flash Player 掛掉
其實該 Bug 是在測試 Adobe AIR JavaScript 時發現的
連帶的導致 AIR 也 Crash
因為 JavaScript 沒有型別檢查功能
不小心就會呼叫到不屬於該物件的方法
平常 Flash 多虧了 AS3 型別檢查
才會讓該問題這麼久沒有浮上檯面

正常情況下,對 Class 呼叫 non-static member 雖然是錯誤的動作
但是也不至於會造成 Flash Player Crash
只要捕捉例外就好
但是對於以上這四行 AS3 程式
try...catch 例外捕捉完全沒用,Flash Player 照樣 Crash

以上 Bug 至少會在以下的 Flash Player 版本發生
Flash Player 9.0.47.0
Flash Player 9.0.115.0
Flash Player 9.0.124.0
Flash Player 10.0.2.54
Flash Player 10.0.12.29
Flash Player 10.0.12.36
Flash Player 10.0.22.87
Flash Player 10.0.32.18

相關連結:
一行 AS3 程式讓 Flash Player 10 死機 Part 5
一行 AS3 程式讓 Flash Player 9 死機 Part 3
一行 AS3 程式讓 Flash Player 9 死機 Part 2
一行 AS3 程式讓 Flash Player 9 死機
用 @* 指定 Attributes 造成 Flash Player 9 Crash

Read more...

2008年5月1日星期四

AS3 - 利用 flash.sampler.getSize 觀察物件大小   [+/-]

Ticore's Blog

Flash Player 9 update 3 (9.0.115.0) 加入了 flash.sampler package
裡面的類別與方法主要都是與記憶體使用有關的
可以在 Flash Player 9 update 3 debug version 與 Adobe AIR 環境中使用
以下簡單利用 flash.sampler.getSize 函式觀察常用物件所占記憶體的大小

ActionScript 3.0 Code:

import flash.sampler.*;
import flash.display.*;

trace("new Number() : ", getSize(new Number()));
trace("new int() : ", getSize(new int()));
trace("new uint() : ", getSize(new uint()));
trace("new Boolean() : ", getSize(new Boolean()));
trace("new Object() : ", getSize(new Object()));
trace("new Array() : ", getSize(new Array()));
trace("new String() : ", getSize(new String()));
trace("new Date() : ", getSize(new Date()));
trace("new XML() : ", getSize(new XML()));
trace("new XMLList() : ", getSize(new XMLList()));
trace("new RegExp() : ", getSize(new RegExp()));
trace("new Function() : ", getSize(new Function()));
trace("new Sprite() : ", getSize(new Sprite()));
trace("new MovieClip() : ", getSize(new MovieClip()));


trace("Number : ", getSize(Number));
trace("int : ", getSize(int));
trace("uint : ", getSize(uint));
trace("Boolean : ", getSize(Boolean));
trace("Object : ", getSize(Object));
trace("Array : ", getSize(Array));
trace("String : ", getSize(String));
trace("Date : ", getSize(Date));
trace("XML : ", getSize(XML));
trace("XMLList : ", getSize(XMLList));
trace("RegExp : ", getSize(RegExp));
trace("Function : ", getSize(Function));
trace("Sprite : ", getSize(Sprite));
trace("MovieClip : ", getSize(MovieClip));


trace("[] : ", getSize([]));
trace("[0] : ", getSize([0]));
trace("[0, 1] : ", getSize([0, 1]));
trace("[null, null] : ", getSize([null, null]));
trace("new Array(0) : ", getSize(new Array(0)));
trace("new Array(1) : ", getSize(new Array(1)));


trace("{} : ", getSize({}));
trace("{a: 'a'} : ", getSize({a: 'a'}));
trace("{a: 'ab'} : ", getSize({a: 'ab'}));
trace("{a: {}} : ", getSize({a: {}}));

trace("{a: 'a', b: 1} : ", getSize({a: 'a', b: 1}));
trace("{a: null, b: null} : ", getSize({a: null, b: null}));


trace("1 : ", getSize(1));
trace("1.1 : ", getSize(1.1));

trace("'A' : ", getSize('A'));
trace("'AB' : ", getSize('AB'));
trace("'ABC' : ", getSize('ABC'));

function fun1():void{};
function fun2(arg1:*):void{var a:* = 1;};

trace("fun1 : ", getSize(fun1));
trace("fun2 : ", getSize(fun2));

輸出結果:

new Number() :  4
new int() :  4
new uint() :  4
new Boolean() :  4
new Object() :  24
new Array() :  40
new String() :  28
new Date() :  32
new XML() :  16
new XMLList() :  32
new RegExp() :  48
new Function() :  588
new Sprite() :  464
new MovieClip() :  496
Number :  1133
int :  856
uint :  856
Boolean :  452
Object :  3282
Array :  4204
String :  3319
Date :  8235
XML :  4818
XMLList :  3118
RegExp :  1008
Function :  977
Sprite :  1602
MovieClip :  2182
[] :  40
[0] :  44
[0, 1] :  48
[null, null] :  48
new Array(0) :  40
new Array(1) :  40
{} :  24
{a: 'a'} :  32
{a: 'ab'} :  32
{a: {}} :  32
{a: 'a', b: 1} :  40
{a: null, b: null} :  40
1 :  4
1.1 :  8
'A' :  30
'AB' :  32
'ABC' :  34
fun1 :  32
fun2 :  32

相關連結:
ActionScript 3 Sampler 相關文件公佈

Read more...

Flash AS3 No Border Scale Background Image   [+/-]

Ticore's Blog

利用 ActionScript 3.0 簡單實作 No Border 等比例縮放的 Background Image

這只有背景圖滿版而已
假如還有其它需要自動調整位置的物件
全部都要個別加以控制
程式碼比起用 Flex 實作多出很多

使用時,須要先準備一個 MovieClip 指定 Class Name 為 MC
作為滿版背景圖之用

ActionScript 3.0 Code:

/*
 Ticore's Blog
 http://ticore.blogspot.com/
*/
package {
 import flash.display.*;
 import flash.events.*;
 
 public class Main extends MovieClip {
  
  public var bg:MovieClip = new MC();
  
  public function Main () {
   
   if (stage) {
    stage.scaleMode = StageScaleMode.NO_SCALE;
    stage.align = "TL";
    stage.addEventListener(Event.RESIZE, onStageResize);
   }
   
   this.addChild(bg);
   onStageResize();
  }
  
  public function onStageResize (evtObj:Event = null):void {
   bg.scaleX = bg.scaleY = 1;
   
   if (!stage) {
    return;
   }
   
   var bgWidth:Number = bg.width;
   var bgHeight:Number = bg.height;
   var stageWidth:Number = stage.stageWidth;
   var stageHeight:Number = stage.stageHeight;
   
   var ratioFlag:Boolean = (stageWidth / stageHeight) > (bgWidth / bgHeight);
   bg.width = ratioFlag ? stageWidth : stageHeight * (bgWidth / bgHeight);
   bg.height = !ratioFlag ? stageHeight : stageWidth * (bgHeight / bgWidth);
   
   bg.x = (stageWidth - bg.width) / 2;
   bg.y = (stageHeight - bg.height) / 2;
  }
  
 }
}

Online Demo

相關連結:
Flex - 簡單實作 No Border Image

Read more...