创建窗体
AIR 主要提供了下列方法用于创建程序窗体:
AIR 自动为每个程序创建第一个窗体。这个窗体根据应用程序描述文件设置进行初始化。如果root上下文已经在描述文件里定义,那么就可以通过Stage.window属性和NativeWindow API来访问window实例的属性和方法。另外,SWF文件的主类必须继承Sprite或Sprite的子类(WindowedApplication和Application组件都是Sprite之类) 如果root上下文是一个HTML文件,这可通过JavaScript Window 对象访问window的属性和方法。
可以创建NativeWindow类实例,通过NativeWindowInitOptions 对象实例作为NativeWindows构造函数的参数进行初始化。可直接通过该对象来访问属性和方法。
可以使用HTML组件的createRootWindow() 方法创建一个窗体用于显示HTML内容。
还可以使用JavaScript Window.open() 方法通过javascript打开一个新窗体。JavaScript创建的窗体只能通过javascript访问其属性和方法,且该窗体只能显示HTML内容。
创建一个新的本地窗体(NativeWindow)
要创建一个新的NativeWindow,可先创建一个NativeWindowInitOptions对象并传递给NativeWindow 构造函数。
var options:NativeWindowInitOptions = new NativeWindowInitOptions();
options.systemChrome = NativeWindowSystemChrome.STANDARD;
options.transparent = false;
var newWin:NativeWindow = new NativeWindow(false, options);
NativeWindow构造函数第一个参数指定是否创建时立即显示该窗体,为了避免显示出如设置大小,位置和内容时窗体所处的中间状态,当你完成窗体初始化后,设置NativeWindow.visible 属性为true。第二个参数为NativeWindowInitOptions对象,该对象用于设置窗体的属性,一旦窗体创建后将不能更改。
注意:设置systemChrome="standard" 和transparent="true" 这种组合不支持。
一旦窗体被创建,你可以用stage属性和Flash显示列表初始化一些属性并载入内容到窗体之上。
注意:要确定操作系统窗体的最大化和最小化大小,可通过NativeWindowCapabilities类得到:
var maxOSSize:Point = NativeWindowsCapabilites.windowMaxSize;
var minOSSize:Point = NativeWindowsCapabilites.windowMinSize;
往窗体中添加内容
要添加内容到本地窗体上,可通过窗体的stage来添加可视化对象。你可以动态创建可视化对象或者通过flash.display.Loader类载入现成的内容。对于HTML窗体,可通过location属性来改变加载的内容或插入HTML内容到DOM。
当你载入包含JavaScript的SWF或HTML内容时必须要考虑到AIR安全模型。任何安全沙箱中的程序,无论是安装的内容或通过url载入的资源都有能力访问到AIR APIs,任何从沙箱外部载入的内容在访问受安全约束的AIR APIs和跨脚本内容时将受到限制。应用程序安全沙箱外部的JavaScript内容将不能使用JavaScript窗体对象的nativeWindow或htmlControl属性。
要想允许安全跨脚本访问,你可以使用flash.system.Door API创建一个严格受限的通讯网关,它提供有限的接口用于程序内容和非程序内容之间的访问。
载入一个SWF 或 图片
可以使用flash.display.Loader类载入flash或图片到本地窗体的显示列表上。
package ...{
????
import flash.display.Sprite;
????
import flash.events.Event;
????
import flash.net.URLRequest;
????
import flash.display.Loader;
????
public class LoadedSWF extends Sprite
????
...{
????????
public function LoadedSWF()...{
????????????
var loader:Loader = new Loader();
????????????
loader.load(new URLRequest("visual.swf"));????????????????????
????????????
loader.contentLoaderInfo.addEventListener(Event.COMPLETE,loadFlash);
????????
}
????????
private function loadFlash(event:Event):void...{
????????????
addChild(event.target.loader);??
????????
}
????
}
}
要在HTML窗体中载入可视化的Flash内容,必须显示在HTML内容的最顶层,或在透明的HTML内容之下。且大小和位置计算独立于HTML内容。
要想在基于HTML的程序中载入包含库代码的SWF文件,最简单的办法就是使用script 标签,也可以直接使用flash.display.Loader API 。
载入HTML内容到本地窗体(NativeWindow)上
要载入HTML内容到本地窗体上,必须在窗体的stage上添加一个HTMLControl控件,然后载入HTML内容到HTML控件上。
//newWindow is a NativeWindow instance
var htmlView:HTMLControl = new HTMLControl();
html.width = newWindow.width;
html.height = newWindow.height;
//set the stage so display objects are added to the top-left and not scaled
newWindow.stage.align = "TL";
newWindow.stage.scaleMode = "noScale";
newWindow.stage.addChild( htmlView );
//urlString is the URL of the HTML page to load
htmlView.load( new URLRequest(urlString) );
要载入HTML页面到HTML窗体上,使用JavaScript方法如window.open 。
要载入HTML页面到Flex 程序上,使用Flex HTML组件。
载入Flash 内容到HTML页面上
在这个Beta版本中,将不支持直接在HTML页面中嵌入Flash内容。页面中的任何Flash对象都将被显示为空白区域,但是使用AIR APIs载入或创建的Flash内容都将作为HTML层的形式存在。
在HTML窗体上层添加Flash内容
因为HTML窗体包含在NativeWindow 实例之内,可以在HTML层的上层或下层中添加Flash可视化对象。
要添加可视化对象到HTML层之上,可通过window.nativeWindow.stage属性的addChild() 方法,addChild()方法将把内容放在任何现成内容之上。
要添加可视化对象到HTML层之下,使用window.nativeWindow.stages属性的addChildAt()方法,传递一个0值作为索引参数,这将导致其他层都向上移动,最后把新加入的对象放在底部。要想让HTML层以下的内容可见,必须设置window.htmlControl对象的paintsDefaultBackground属性为false。
下面的例子演示如何添加一个flash对象,该例子创建了两个图形对象,一个添加在HTML层下面,一个在上面。
<html>
<head>
<title>Bouncers</title>
<script src="AIRAliases.js" type="text/javascript"></script>
<script language="JavaScript" type="text/javascript">...
air.Shape = window.runtime.flash.display.Shape;
function Bouncer(radius, color)...{
this.radius = radius;
this.color = color;
//velocity??
this.vX = -1.3;
this.vY = -1;
//Create a Shape object and draw a circle with its graphics property
this.shape = new air.Shape();????
this.shape.graphics.lineStyle(1,0);
this.shape.graphics.beginFill(this.color,.9);
this.shape.graphics.drawCircle(0,0,this.radius);
this.shape.graphics.endFill();
//Set the starting position
this.shape.x = 100;
this.shape.y = 100;
//Moves the sprite by adding (vX,vY) to the current position
this.update = function()...{
this.shape.x += this.vX;
this.shape.y += this.vY;
//Keep the sprite within the window
if( this.shape.x - this.radius < 0)...{??
this.vX = -this.vX;
}
if( this.shape.y - this.radius < 0)...{
this.vY = -this.vY;
}
if( this.shape.x??+ this.radius > window.nativeWindow.stage.stageWidth)...{
this.vX = -this.vX;
}
if( this.shape.y??+ this.radius > window.nativeWindow.stage.stageHeight)...{
this.vY = -this.vY;
}
};
}
function init()...{
//turn off the default HTML background
window.htmlControl.paintsDefaultBackground = false;
var bottom = new Bouncer(60,0xff2233);
var top = new Bouncer(30,0x2441ff);
//listen for the enterFrame event
window.htmlControl.addEventListener("enterFrame",function(evt)...{
bottom.update();
top.update();
});
//add the bouncing shapes to the window stage
window.nativeWindow.stage.addChildAt(bottom.shape,0);
window.nativeWindow.stage.addChild(top.shape);
}
</script>
<body onload="init();">
<h1>de Finibus Bonorum et Malorum</h1>
<p>Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium
doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis
et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia
voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui
ratione voluptatemsequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia
dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora
incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam,
quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea
commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit
esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas
nulla pariatur?</p>
<p style="background-color:#FFFF00; color:#660000;">This paragraph has a background color.</p>
<p>At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis
praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias
excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui
officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem
rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est
eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus,
omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam
et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates
repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a
sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut
perferendis doloribus asperiores repellat.</p>
</body>
</html>
示例:用ActionScript创建窗体
下面的例子演示如何创建新窗体:
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"??
layout="absolute" applicationComplete="createNativeWindow();">
<mx:Script>
<![CDATA[
public function createNativeWindow():void{
//create the init options
var options:NativeWindowInitOptions =
new NativeWindowInitOptions();
options.transparent = false;
options.systemChrome = NativeWindowSystemChrome.STANDARD;
options.type = NativeWindowType.NORMAL;
//create the window
var newWindow:NativeWindow = new NativeWindow(false,options);
newWindow.title = "A title";
newWindow.width = 600;
newWindow.height = 400;
//add a sprite to the window
newWindow.stage.align = StageAlign.TOP_LEFT;
newWindow.stage.scaleMode = StageScaleMode.NO_SCALE;
//show the new window
newWindow.visible = true;
}
]]>
</mx:Script>
</mx:WindowedApplication>
控制窗体
这一章节讨论如何使用NativeWindow类的属性和方法控制应用程序窗体的外观和行为。
得到NativeWindow实例
要想操作窗体,必须先得到窗体实例,可在下面这些地方得到窗体实例:
窗体构造函数
也就是新建NativeWindow所用的构造函数.
窗体的stage
也就是stage.nativeWindow
任何可视化对象的stage
也就是myDisplayObject.stage.nativeWindow.
窗体事件
Event对象的target属性指向窗体引用
HTMLControl或HTML窗体的全局属性nativeWindow
也就是window.nativeWindow.
Shell 对象
Shell.shell.activeWindow 指向应用程序的活动窗体(激活状态,如果没有任何窗体处于激活状态则返回null)。Shell.shell.openedWindows数组包含应用程序中所有未被打开的窗体。
因为Flex Application, WindowedApplication, 和Window 对象都是可视化对象,我们可以很容易通过stage属性得到窗体引用:
<?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>
激活,显示,隐藏窗体
调用NativeWindow.activate()方法激活一个窗体,激活窗体后将使窗体显示在最顶层,开始获得键盘和鼠标焦点,如果有必要可恢复window的visible属性或设置visible=true,激活一个窗体并不会改变其他窗体的顺序。
要想显示没有激活的隐藏窗体,可设置其visible属性为true,这将使窗体显示在最顶层,但是由于未激活,不能接收键盘和鼠标反应。
要隐藏窗体,可设置NativeWindow.visible属性为false。隐藏一个窗体将取消窗体的显示以及相关的任何栏图标。
最大化,最小化和还原窗体
使用NativeWindow.maximize()方法使窗体最大化显示
myWindow.maximize();
使用NativeWindow.minimize()方法使窗体最小化显示
myWindow.minimize();
还原一个窗体指恢复到最大化和最小化之前的状体。
myWindow.restore();
改变窗体显示顺序
AIR为窗体提供两组显示顺序,由alwaysInFront 属性进行控制。通过设置alwaysInFront=false,意思是把窗体放在正规的组群众,大多数窗体都放在这里。而第二个组群所放的窗体总是显示在正规组群窗体的上层。如果没有这个特殊组群的话,改变窗体顺序将会显得非常混乱,下列情况都将用到这个窗体组群:
l 临时的弹出式窗体,比如提示框,弹出式列表,自定义菜单或组合框,因为这些窗体用完即关闭。
l 屏幕保护
l 一些急需的错误信息框
l 生命周期很短的窗体
l 游戏或视频的全屏窗体
NativeWindow类提供下列方法用于设置窗体之间的显示顺序:
alwaysInFront 属性
指定使用哪个窗体组,一般情况下alwaysInFront=false ,如果设为true,这表示所有窗体都处于顶层位置(只是没有激活),如果在设为false,表示把窗体放入正规组的顶层(但是仍在顶层组的后面)。设置该值并不会改变窗体的顺序。
orderToFront()
设置该窗体为组群中最前
orderInFrontOf()
设置该窗体排在某窗体之前
orderToBack()
设置该窗体为组群中最后
orderBehind()
设置该窗体排在某窗体之后
注意:如果该窗体被隐藏或最小化,调用这些方法将无效。
关闭窗体
使用NativeWindow.close方法关闭窗体
关闭一个窗体将卸载该窗体所包含的内容,不过如果还有其他对象引用这些内容,将不会被销毁。NativeWindow.close()方法的执行是异步的,应用程序仍然在关闭窗体过程中继续运行,当关闭完成时,该close方法将触发一个close事件。窗体被关闭后将无法访问其大部分属性和方法,否则会抛出IllegalOperationError异常,关闭的窗体将不能再次打开,可通过closed属性检测窗体是否已被关闭。要简单的隐藏窗体,只要设置其visible属性为false就可以了。
如果Shell.autoExit属性为true(默认设置),当应用程序的所有窗体都关闭后,程序也将停止运行。
允许撤销对窗体的操作
当窗体使用操作系统窗体风格,用户与窗体的交互可通过一些事件进行取消,比如说,单用户点击一个窗体上系统菜单的关闭按钮,这closing事件将被触发,任何注册的监听器调用preventDefault()方法可以取消关闭窗体。
如果窗体不使用系统窗体风格,这需要手动出发相应的事件。如果你调用一个方法要关闭窗体或改变窗体大小或设置bounds属性,这些改变将不能被取消,除非在窗体发生变化之前通知应用程序,应用程序逻辑通过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()方法检测是否已经取消操作。
例子:最小化,最大化,还原和关闭窗体
下面的这段代码演示窗体的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>
例子:改变大小和移动窗体
使用NativeWindow.startResize()方法改变窗体大小,该方法实际上是触发系统控制功能来改变窗体大小。当该方法在mouseDown 事件里调用时,大小改变是由鼠标确定的,当系统接收到mouseUp事件则停止大小调整。
如果不改变大小只移动窗体,可使用NativeWindow.startMove()方法,和startResize()方法一样,当startMove()方法mouseDown 事件里调用时,窗体移动过程是由鼠标确定的,直到系统接收到鼠标的mouseUp事件。
下面的这个例子演示如何初始化改变窗体大小和移动窗体操作:
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 trigger a 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 trigger a 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();
????????
}
????
}
}
监听窗体事件
如要监听窗体发出的事件,可通过窗体注册一个监听器,例如,要监听closing事件,用下面的代码注册:
myWindow.addEventListener(Event.CLOSING, onClosingEvent);
当事件发出时,窗体引用的target属性发出该事件。
大多数窗体事件都有两种消息,第一个消息是该窗体的变化快要临近(是可以取消的),而另一个消息表示变化已经发生。例如,当用户点击关闭按钮,则closing事件消息被触发,如果没有监听器取消该事件,则窗体被关闭。
flash.events.Event 类的相关事件:
ACTIVATE
DEACTIVATE
CLOSING
CLOSE
NativeWindowBoundsEvent:
使用beforeBounds和afterBounds属性来检测窗体边界是否即将改变或已经完成改变。
MOVING
MOVE
RESIZING
RESIZE
NativeWindowDisplayStateEvent:
使用beforeDisplayState和afterDisplayState 属性检测窗体改变状态是即将改变还是已经完成改变。
DISPLAY_STATE_CHANGING
DISPLAY_STATE_CHANGE
使用全屏模式
这是Stage的displayState属性为StageDisplayState.FULL_SCREEN使窗体进入全屏模式,全屏模式下鼠标和键盘仍有效。(如果在浏览器中运行的SWF,这键盘无效),如要退出全屏模式,只要点击ESC键即可。
例如,下面的Flex代码定义一个简单全屏模式的AIR应用程序:
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"??
layout="vertical"??
applicationComplete="init()" backgroundColor="0x003030" focusRect="false">
<mx:Script>
<![CDATA[
private function init():void??
{
stage.displayState = StageDisplayState.FULL_SCREEN;
focusManager.setFocus(terminal);
terminal.text = "Welcome to the dumb terminal app. Press the ESC key to exit.. ";
terminal.selectionBeginIndex = terminal.text.length;
terminal.selectionEndIndex = terminal.text.length;
}
]]>
</mx:Script>
<mx:TextArea??
id="terminal"??
height="100%" width="100%"??
scroll="false"
backgroundColor="0x003030"??
color="0xCCFF00"??
fontFamily="Lucida Console"??
fontSize="44"/>
</mx:WindowedApplication>
屏幕
根据AIR screen API可以获得系统桌面显示屏幕的信息。
屏幕简介
screen API包含一个简单类,Screen,获得系统屏幕信息和屏幕的详细描述。
计算机系统可能有多个监视器或显示设备,这样对应的多个桌面屏幕排列在虚拟空间上。AIR Screen类提供了关于屏幕信息,如果有多个监视器映射到同一个屏幕上,那只有一个屏幕可显示,如果屏幕的尺寸大于监视器显示范围,没有办法确定是哪一部分处于可视状态。
一个屏幕表示一个独立的桌面显示区域,被描述为虚拟桌面的一个矩形区域,屏幕左上角为初始坐标,单位为像素。
点击查看附件
上面的屏幕排列中,虚拟桌面上有两个屏幕,主屏幕(#1)的左上角坐标总是(0,0),如果屏幕排列设置屏幕#2作为主屏幕,则屏幕#1的坐标将为负坐标,一般指屏幕的可使用边界不包括菜单栏,任务栏。
枚举屏幕
通过下列屏幕方法和属性枚举虚拟桌面上的屏幕:
Screen.screens
数组对象,表示可用的屏幕,注意数组的元素顺序不是有效的。
Screen.mainScreen
表示代表主屏幕的屏幕对象,在Mac OS X系统中,主屏幕为显示菜单栏的所在屏幕,在Windows中为系统指定的主屏幕。
Screen.getScreensForRectangle()
通过指定的区域获得屏幕对象数组,该矩形区域作为参数传递给该方法,如果没有屏幕在范围内则返回空数组。
示例:在屏幕中移动窗体
这个例子使用screen API通过方向键在多个屏幕中移动窗体。
package ...{
????
import flash.display.Sprite;
????
import flash.display.Screen;
????
import flash.events.KeyboardEvent;
????
import flash.ui.Keyboard;
????
import flash.display.StageAlign;