管理視窗

Adobe AIR 1.0 以及更新的版本

您可以使用 NativeWindow 類別的屬性和方法來管理桌面視窗的外觀、行為方式和效期。

備註: 使用 Flex 架構時,通常最好使用架構類別來管理視窗行為。大部分的 NativeWindow 屬性和方法都可以透過 mx:WindowedApplication 和 mx:Window 類別存取。

取得 NativeWindow 實體

操控視窗之前,必須先取得視窗實體。您可以從下列其中一個位置取得視窗實體:

  • 用來建立視窗的原生視窗建構函式:

    var win:NativeWindow = new NativeWindow(initOptions);
  • 視窗舞台的 nativeWindow 屬性:

    var win:NativeWindow = stage.nativeWindow;
  • 視窗中顯示物件的 stage 屬性:

    var win:NativeWindow = displayObject.stage.nativeWindow;
  • 視窗所傳送之原生視窗事件的 target 屬性:

    private function onNativeWindowEvent(event:NativeWindowBoundsEvent):void 
    { 
        var win:NativeWindow = event.target as NativeWindow; 
    }
  • 視窗中顯示之 HTML 頁面的 nativeWindow 屬性:

    var win:NativeWindow = htmlLoader.window.nativeWindow;
  • NativeApplication 物件的 activeWindow openedWindows 屬性:

    var nativeWin:NativeWindow = NativeApplication.nativeApplication.activeWindow; 
    var firstWindow:NativeWindow = NativeApplication.nativeApplication.openedWindows[0];

    NativeApplication.nativeApplication.activeWindow 會參考應用程式的作用中視窗 (但如果作用中視窗不是此 AIR 應用程式的視窗,則會傳回 null )。 NativeApplication.nativeApplication.openedWindows 陣列會包含尚未關閉之 AIR 應用程式中的所有視窗。

由於 Flex 的 mx:WindowedApplication 和 mx:Window 物件都是顯示物件,您可以使用 stage 屬性,輕鬆地參照 XML 檔案中的應用程式視窗,如下所示:

<?xml version="1.0" encoding="utf-8"?> 
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" applicationComplete="init();"> 
    <mx:Script> 
        <![CDATA[ 
            import flash.display.NativeWindow; 
 
            public function init():void{ 
                var appWindow:NativeWindow = this.stage.nativeWindow; 
                //set window properties 
                appWindow.visible = true; 
            } 
        ]]> 
    </mx:Script> 
</WindowedApplication
備註: 直到 Flex 架構將 WindowedApplication 或 Window 組件加入視窗舞台之前,組件的 stage 屬性都會是 null 。這種行為方式與 Flex Application 組件一致,但並不表示您無法在 WindowedApplication 和 Window 組件的初始化週期中稍早發生之事件 (例如 creationComplete ) 的偵聽程式中,存取 stage 或 NativeWindow 實體。傳送 applicationComplete 事件時,可以安全地存取 stage 和 NativeWindow 實體。

啟用、顯示及隱藏視窗

若要啟用視窗,請呼叫 NativeWindow activate() 方法。啟用視窗會將視窗移到前面,給予它鍵盤和滑鼠焦點,而且必要時,也會還原視窗或將 visible 屬性設定為 true ,以顯示視窗。啟用視窗不會變更應用程式中其它視窗的順序。呼叫 activate() 方法會導致視窗傳送 activate 事件。

若要顯示隱藏的視窗而不加以啟用,請將 visible 屬性設定為 true 。這會將視窗移到前面,但不會指定焦點給該視窗。

若要隱藏視窗不讓人看見,請將其 visible 屬性設定為 false 。隱藏視窗會同時抑制視窗的顯示以及任何相關的工作列圖示,而在 Mac OS X 上,則會抑制 Windows 選單項目的顯示。

當您變更視窗的可見性時,該視窗擁有的任何視窗可見性也會隨之改變。例如,如果您隱藏視窗,也會同時隱藏其擁有的所有視窗。

備註: 在 Mac OS X 中,無法完全隱藏在視窗停駐位置具有圖示的最小化視窗。如果最小化視窗上的 visible 屬性設定為 false ,那麼視窗的停駐圖示仍然會顯示。如果使用者按一下圖示,視窗會還原為可見的狀態並顯示。

變更視窗顯示順序

AIR 提供多個方法,可用來直接變更視窗的顯示順序。您可以在顯示順序中將視窗向前或向後移動;也可以將視窗移到另一個視窗的上方或後方。同時,使用者也可以透過啟用視窗,重新排列視窗的順序。

您可以將視窗的 alwaysInFront 屬性設定為 true ,讓視窗保持在其它視窗前面。如果有多個視窗具備此設定,則這些視窗的顯示順序為彼此間的排序順序,但是它們永遠都會排列在將 alwaysInFront 設定為 false 的視窗上方。

在最上端群組中的視窗也會顯示在其它應用程式中視窗的上方,即使 AIR 應用程式不在作用中也是如此。因為這項行為方式可能會對使用者造成困擾,請只在需要及適當時,將 alwaysInFront 設定為 true 。適合使用的範例包括:

  • 控制項的暫時性彈出式視窗,例如工具提示、彈出式清單、自訂選單,或下拉式清單方塊。由於這些視窗會在失去焦點時關閉,因此可以避免妨礙使用者檢視另一個視窗的擾人情況。

  • 極端緊急的錯誤訊息和警告。當使用者未適時回應而可能會發生無法挽回的變更時,就應該將警告視窗推到最前面。但是,多半錯誤和警告都可以依一般視窗顯示順序處理。

  • 短效期的 Toast 樣式視窗。

備註: AIR 不會強制在適當的狀況下使用 alwaysInFront 屬性。但是,如果您的應用程式中斷了使用者的工作流程,很可能會寄存在該使用者的垃圾筒裡。

如果某個視窗擁有其他視窗,則這些視窗永遠都會排序在它前面。如果您在擁有其他視窗的視窗上,呼叫 orderToFront() 或將 alwaysInFront 設為 true ,則會將擁有的視窗連同擁有者視窗一起重新排序在其他視窗的前面,但是擁有的視窗仍然會顯示在擁有者的前面。

在擁有的視窗上呼叫視窗排序方法,通常可在相同視窗所擁有的視窗之間正常運作,但是相較於該群組外面的視窗,也可能會變更擁有的視窗整個群組的順序。例如,如果您在擁有的視窗上呼叫 orderToFront() ,則會將該視窗、其擁有者及相同擁有者擁有的任何其他視窗都移到視窗顯示順序的前面。

NativeWindow 類別會提供下列屬性和方法,以供設定視窗相對於其它視窗的顯示順序:

成員

說明

alwaysInFront 屬性

指定視窗是否顯示於最上層的視窗群組。

幾乎在所有情況下, false 會是最好的設定。將值從 false 變更為 true ,會將視窗移到所有視窗的前面 (但不會加以啟用)。將值從 true 變更為 false ,會將該視窗排列在最上層群組中其餘視窗的後面,但仍然在其它視窗的前面。將視窗的屬性設定為其目前的值並不會變更該視窗的顯示順序。

alwaysInFront 設定對於其他視窗擁有的視窗沒有影響。

orderToFront()

將視窗顯示在最前面。

orderInFrontOf()

將此視窗直接移到特定視窗的前面。

orderToBack()

將視窗傳送到其它視窗的後面。

orderBehind()

將視窗直接傳送到特定視窗的後面。

activate()

將視窗移到前面 (同時也讓視窗顯示為可見,並指定焦點)。

備註: 如果視窗是隱藏的 ( visible false ) 或最小化,則呼叫顯示順序的方法沒有任何作用。

在 Linux 作業系統中,不同的視窗管理員會針對視窗的顯示順序強制執行不同的規則:

  • 在部分視窗管理員中,公用程式視窗永遠會顯示在一般視窗的前面。

  • 在部分視窗管理員中,將 alwaysInFront 設為 true 的全螢幕視窗永遠會顯示在其它同樣將 alwaysInFront 設為 true 的視窗前面。

關閉視窗

若要關閉視窗,請使用 NativeWindow.close() 方法。

關閉視窗會取消載入視窗內容,但如果其它物件參考此內容,就不會刪除此內容物件。 NativeWindow.close() 方法會以非同步的方式執行,在關閉處理中,視窗所包含的應用程式會繼續執行。close 方法會在關閉作業完成時傳送 close 事件。就技術層面來看,NativeWindow 物件仍然有效,但在已關閉視窗上存取大部分屬性和方法,會產生 IllegalOperationError。您不能重新開啟已關閉的視窗。請檢查視窗的 closed 屬性,以測試視窗是否已關閉。若只是要隱藏視窗不讓人看見,請將 NativeWindow.visible 屬性設定為 false

如果 Nativeapplication.autoExit 屬性是 true ,這是預設值,則在最後一個視窗關閉時,應用程式就會結束。

任何具有擁有者的視窗都會在擁有者關閉時同時關閉。擁有的視窗不會傳送 closing 事件,因此無法防止關閉。會傳送 close 事件。

允許取消視窗作業

當視窗使用系統顏色時,使用者與視窗之間的互動可以透過偵聽並取消應用程式事件的預設行為方式加以取消。例如,當使用者按一下系統顏色關閉按鈕時,就會傳送 closing 事件。如果任何已登錄偵聽程式呼叫該事件的 preventDefault() 方法,則視窗就不會關閉。

當視窗不使用系統顏色時,就不會在變更進行之前,自動傳送預期變更的通知事件。因此,如果您呼叫關閉視窗的方法、變更視窗狀態,或設定任何視窗邊界屬性,都無法取消變更。若要在視窗進行變更之前通知應用程式中的組件,您的應用程式邏輯可以使用視窗的 dispatchEvent() 方法,傳送相關的通知事件。

例如,下列邏輯會實作視窗關閉按鈕的可取消事件處理常式:

public function onCloseCommand(event:MouseEvent):void{ 
    var closingEvent:Event = new Event(Event.CLOSING,true,true); 
    dispatchEvent(closing); 
    if(!closingEvent.isDefaultPrevented()){ 
        win.close(); 
    } 
} 

如果偵聽程式呼叫事件 preventDefault() 方法,則 dispatchEvent() 方法會傳回 false 。但是,它也可能會在其它原因之下傳回 false ,所以最好是明確地使用 isDefaultPrevented() 方法來測試是否應該取消變更。

最大化、最小化和還原視窗

若要將視窗最大化,請使用 NativeWindow maximize() 方法。

myWindow.maximize(); 

若要將視窗最小化,請使用 NativeWindow minimize() 方法。

myWindow.minimize(); 

若要還原視窗 (也就是,回復到最小化或最大化之前的大小),請使用 NativeWindow restore() 方法。

myWindow.restore(); 

擁有視窗最小化或還原時,也會最小化和還原具有擁有者的視窗。擁有的視窗因為其擁有者最小化而最小化時,擁有的視窗不會傳送任何事件。

備註: 最小化 AIR 視窗產生的行為與 Mac OS X 的標準行為不同。AIR 視窗不會在應用程式定義的「標準」大小與使用者所設定最後大小之間切換,而會在應用程式或使用者最後設定的大小與螢幕的完整可使用區域之間切換。

在 Linux 作業系統中,不同的視窗管理員會針對視窗顯示狀態設定強制執行不同的規則:

  • 在部分視窗管理員中,公用程式視窗無法最大化。

  • 若視窗已設定最大大小時,部分視窗會不允許最大化視窗。也有部分視窗管理員會將顯示狀態設定為最大化,但不會調整視窗大小。這兩種情況都不會傳送顯示狀態變更事件。

  • 部分視窗管理員不會理會視窗的 maximizable minimizable 設定。

備註: 在 Linux 中,視窗屬性會以非同步的方式變更。如果您在程式的某一行變更了顯示狀態,然後在下一行中讀取該值,所讀取的值仍然會反映舊的設定。不論在哪個平台上,NativeWindow 物件在顯示狀態變更時都會傳送 displayStateChange 事件。如果您需要根據視窗的新狀態來採取某些動作,請務必在 displayStateChange 事件處理常式中執行。請參閱 偵聽視窗事件

範例:最大化、最小化、還原與關閉視窗

下列簡短的 MXML 應用程式會示範 Window maximize() minimize() restore() close() 方法:

<?xml version="1.0" encoding="utf-8"?> 
 
<mx:WindowedApplication  
    xmlns:mx="http://www.adobe.com/2006/mxml"  
    layout="vertical"> 
     
     
    <mx:Script> 
    <![CDATA[ 
    public function minimizeWindow():void 
    { 
        this.stage.nativeWindow.minimize(); 
    } 
 
    public function maximizeWindow():void 
    { 
        this.stage.nativeWindow.maximize(); 
    }           
     
    public function restoreWindow():void 
    { 
        this.stage.nativeWindow.restore(); 
    }           
 
    public function closeWindow():void 
    { 
        this.stage.nativeWindow.close(); 
    } 
    ]]> 
    </mx:Script> 
 
    <mx:VBox> 
        <mx:Button label="Minimize" click="minimizeWindow()"/> 
        <mx:Button label="Restore" click="restoreWindow()"/> 
        <mx:Button label="Maximize" click="maximizeWindow()"/> 
        <mx:Button label="Close" click="closeWindow()"/> 
    </mx:VBox> 
 
</mx:WindowedApplication>

下列 Flash 的 ActionScript 範例會建立四個可點選的文字欄位,這些欄位會觸發 NativeWindow minimize() maximize() restore() close() 方法:

package 
{ 
    import flash.display.Sprite; 
    import flash.events.MouseEvent; 
    import flash.text.TextField; 
     
    public class MinimizeExample extends Sprite 
    { 
        public function MinimizeExample():void  
        { 
            var minTextBtn:TextField = new TextField(); 
            minTextBtn.x = 10; 
            minTextBtn.y = 10; 
            minTextBtn.text = "Minimize"; 
            minTextBtn.background = true; 
            minTextBtn.border = true; 
            minTextBtn.selectable = false; 
            addChild(minTextBtn); 
            minTextBtn.addEventListener(MouseEvent.CLICK, onMinimize); 
         
            var maxTextBtn:TextField = new TextField(); 
            maxTextBtn.x = 120; 
            maxTextBtn.y = 10; 
            maxTextBtn.text = "Maximize"; 
            maxTextBtn.background = true; 
            maxTextBtn.border = true; 
            maxTextBtn.selectable = false; 
            addChild(maxTextBtn); 
            maxTextBtn.addEventListener(MouseEvent.CLICK, onMaximize); 
         
            var restoreTextBtn:TextField = new TextField(); 
            restoreTextBtn.x = 230; 
            restoreTextBtn.y = 10; 
            restoreTextBtn.text = "Restore"; 
            restoreTextBtn.background = true; 
            restoreTextBtn.border = true; 
            restoreTextBtn.selectable = false; 
            addChild(restoreTextBtn); 
            restoreTextBtn.addEventListener(MouseEvent.CLICK, onRestore); 
             
            var closeTextBtn:TextField = new TextField(); 
            closeTextBtn.x = 340; 
            closeTextBtn.y = 10; 
            closeTextBtn.text = "Close Window"; 
            closeTextBtn.background = true; 
            closeTextBtn.border = true; 
            closeTextBtn.selectable = false; 
            addChild(closeTextBtn); 
            closeTextBtn.addEventListener(MouseEvent.CLICK, onCloseWindow); 
        } 
        function onMinimize(event:MouseEvent):void 
        { 
            this.stage.nativeWindow.minimize(); 
        } 
        function onMaximize(event:MouseEvent):void 
        { 
            this.stage.nativeWindow.maximize(); 
        } 
        function onRestore(event:MouseEvent):void 
        { 
            this.stage.nativeWindow.restore(); 
        } 
        function onCloseWindow(event:MouseEvent):void 
        { 
            this.stage.nativeWindow.close(); 
        } 
    } 
}

調整視窗大小及移動視窗

當視窗使用系統顏色時,該設定會提供拖曳控制項,以供調整視窗大小,並在桌面上四處移動視窗。如果視窗不使用系統顏色,則必須自行加入控制項,以便讓使用者調整視窗大小及移動視窗。

備註: 若要調整視窗大小或移動視窗,必須先取得 NativeWindow 實體的參考。如需有關如何取得視窗參考的詳細資訊,請參閱 取得 NativeWindow 實體

調整視窗大小

若要讓使用者以互動方式調整視窗大小,請使用 NativeWindow 的 startResize() 方法。從 mouseDown 事件呼叫此方法時,調整大小作業會由滑鼠驅動,並在作業系統接到 mouseUp 事件時完成。呼叫 startResize() 時,會傳入引數,指定要開始調整視窗大小的邊緣或角落。

若要以程式設計的方式設定視窗大小,請將視窗的 width height bounds 屬性設定為所需的尺寸。當您設定邊界時,視窗的大小和位置都可以同時變更。不過,無法保證會依照何種順序變更。部分 Linux 視窗管理員不允許視窗延伸到桌面螢幕的邊界之外。在這種情況下,最終的視窗大小可能會因為屬性的設定順序而遭到限制,即便這些變更的最終效果可能因為順序不同而讓視窗合法。例如,如果您為接近畫面底部的視窗同時變更高度和 y 座標,則如果高度是在 y 座標進行變更之前套用,對於高度所做的完整變更可能就不會生效。

備註: 在 Linux 中,視窗屬性會以非同步的方式變更。如果您在程式的某一行調整視窗大小,然後在下一行中讀取其尺寸,則尺寸仍然會反映舊的設定。不論在哪個平台上,NativeWindow 物件在視窗調整大小時都會傳送 resize 事件。如果您需要根據視窗新的大小或狀態來採取某些動作 (例如在視窗中配置控制項),請務必在 resize 事件處理常式中執行。請參閱 偵聽視窗事件

舞台的縮放模式會決定在調整視窗大小時,視窗舞台及其內容的行為。請記住,舞台縮放模式是針對情況 (如網頁瀏覽器) 而設計,而不是由應用程式控制其顯示空間的大小和比例。一般來說,您可以將舞台 scaleMode 屬性設定為 StageScaleMode.NO_SCALE ,取得最佳效果。如果您要縮放視窗的內容,仍然可以設定內容的 scaleX scaleY 參數,以因應視窗邊界的變更。

移動視窗

若要移動視窗而不調整其大小,請使用 NativeWindow startMove() 方法。就像 startResize() 方法一樣,從 mouseDown 事件呼叫 startMove() 方法時,移動程序是由滑鼠驅動的,而當作業系統接到 mouseUp 事件時,就已完成程序。

如需有關 startResize() startMove() 方法的詳細資訊,請參閱 適用於 Adobe Flash Platform 的 ActionScript 3.0 參考

若要以程式設計的方式移動視窗,請將視窗的 x y bounds 屬性設為所需的位置。設定邊界時,視窗的大小和位置可以同時變更。

備註: 在 Linux 中,視窗屬性會以非同步的方式變更。如果您在程式的某一行移動了視窗,然後在下一行中讀取其位置,所讀取的值仍然會反映舊的設定。不論在哪個平台上,NativeWindow 物件在位置變更時都會傳送 move 事件。如果您需要根據視窗的新位置來採取某些動作,請務必在 move 事件處理常式中執行。請參閱 偵聽視窗事件

範例:調整視窗大小及移動視窗

下列範例會說明如何在視窗上開始進行調整大小及移動作業:

package 
{ 
    import flash.display.Sprite; 
    import flash.events.MouseEvent; 
    import flash.display.NativeWindowResize; 
 
    public class NativeWindowResizeExample extends Sprite 
    { 
        public function NativeWindowResizeExample():void 
        { 
            // Fills a background area. 
            this.graphics.beginFill(0xFFFFFF); 
            this.graphics.drawRect(0, 0, 400, 300); 
            this.graphics.endFill(); 
     
            // Creates a square area where a mouse down will start the resize. 
            var resizeHandle:Sprite =  
                createSprite(0xCCCCCC, 20, this.width - 20, this.height - 20); 
            resizeHandle.addEventListener(MouseEvent.MOUSE_DOWN, onStartResize); 
     
            // Creates a square area where a mouse down will start the move. 
            var moveHandle:Sprite = createSprite(0xCCCCCC, 20, this.width - 20, 0); 
            moveHandle.addEventListener(MouseEvent.MOUSE_DOWN, onStartMove); 
        } 
     
        public function createSprite(color:int, size:int, x:int, y:int):Sprite 
        { 
            var s:Sprite = new Sprite(); 
            s.graphics.beginFill(color); 
            s.graphics.drawRect(0, 0, size, size); 
            s.graphics.endFill(); 
            s.x = x; 
            s.y = y; 
            this.addChild(s);     
            return s;         
        } 
     
        public function onStartResize(event:MouseEvent):void 
        { 
            this.stage.nativeWindow.startResize(NativeWindowResize.BOTTOM_RIGHT); 
        } 
 
        public function onStartMove(event:MouseEvent):void 
        { 
            this.stage.nativeWindow.startMove(); 
        } 
    } 
}