近日工作中需要用到类似Windows那种罕有最大化、最小化、关闭功能的TitleWindow,而Flex本身并无这个组件(Flex AI有NativeWindow这个组件)。于是上网搜索,发现了MDI,但是感觉代码太多而且代码侵入性很强不便于扩展,其更适合与在一个空间内存在多个Panel的场景,ResizeTitleWindow与ResizeManage更使用于我的应用场景,我最终使用的是ResizeManag这个组件但不幸的是下载下来的资源也是有残缺,心想反正自己也是得做扩展的因而放弃了寻找完全可用版的努力,继而开始研究源代码并进行了相应的修改与扩展。
ResizeWindow.as
package sjd.containers
{
import flash.events.MouseEvent;
import flash.geom.Point;
import mx.containers.Form;
import mx.containers.FormItem;
import mx.containers.TitleWindow;
import mx.controls.Button;
import mx.controls.TextInput;
import mx.core.Application;
import mx.events.FlexEvent;
import sjd.utils.CursorUtil;
[Event(name="closeWindow", type="mx.events.FlexEvent")]
[Event(name="minWindow", type="mx.events.FlexEvent")]
[Event(name="maxWindow", type="mx.events.FlexEvent")]
/**
* @class ResizeWindow
* @brief A TitleWindow with Resize Enabled and Max, Min, Close Button
* @author Jove
* @version 1.1
*/
public class ResizeWindow extends TitleWindow{
private static const SIDE_OTHER:Number = 0;
private static const SIDE_TOP:Number = 1;
private static const SIDE_BOTTOM:Number = 2;
private static const SIDE_LEFT:Number = 4;
private static const SIDE_RIGHT:Number = 8;
private static var resizeObj:Object;
private static var mouseState:Number = 0;
private static var mouseMargin:Number = 10;
[Embed(source="/sjd/assets/verticalSize.gif")]
private var verticalSize:Class;
[Embed(source="/sjd/assets/horizontalSize.gif")]
private var horizontalSize:Class;
[Embed(source="/sjd/assets/leftObliqueSize.gif")]
private var leftObliqueSize:Class;
[Embed(source="/sjd/assets/rightObliqueSize.gif")]
private var rightObliqueSize:Class;
private var oWidth:Number = 0;
private var oHeight:Number = 0;
private var oX:Number = 0;
private var oY:Number = 0;
private var oPoint:Point = new Point();
private var _showWindowButtons:Boolean = true;
private var _windowMinSize:Number = 150;
//private var form:MyForm = new MyForm();
/**
* Constructor.
* Add mouse envent to this window and application.
* initialize the old positions.
*/
public function ResizeWindow(){
super();
addContent();
initPosition(this);
this.addEventListener(MouseEvent.MOUSE_MOVE, oMouseMove);
this.addEventListener(MouseEvent.MOUSE_OUT, oMouseOut);
this.addEventListener(MouseEvent.MOUSE_DOWN, oMouseDown);
//this.addEventListener(MouseEvent.MOUSE_UP, oMouseUp);
this.addEventListener(FlexEvent.CREATION_COMPLETE, addButton);
//Application.application.parent:SystemManager
Application.application.parent.addEventListener(MouseEvent.MOUSE_UP, oMouseUp);
Application.application.parent.addEventListener(MouseEvent.MOUSE_MOVE, oResize);
}
private function addContent():void{
var form:Form = new Form();
var formItem1:FormItem = new FormItem();
formItem1.label = "事件源";
var text:TextInput = new TextInput();
formItem1.addChild(text);
form.width = 200;
form.addChild(formItem1);
//form.width = this.width;
//form.height = this.height;
this.addChild(form);
//this.updateDisplayList(100,100);
}
public function set showWindowButtons(show:Boolean):void{
_showWindowButtons = show;
if(titleBar != null){
addButton(new FlexEvent(""));
}
}
public function get showWindowButtons():Boolean{
return _showWindowButtons;
}
public function set windowMinSize(size:Number):void{
if(size > 0){
_windowMinSize = size;
}
}
public function get windowMinSize():Number{
return _windowMinSize;
}
private static function initPosition(obj:Object):void{
obj.oHeight = obj.height;
obj.oWidth = obj.width;
obj.oX = obj.x;
obj.oY = obj.y;
}
/**
* Set the first global point that mouse down on the window.
* @param The MouseEvent.MOUSE_DOWN
*/
private function oMouseDown(event:MouseEvent):void{
if(mouseState != SIDE_OTHER){
resizeObj = event.currentTarget;
initPosition(resizeObj);
oPoint.x = resizeObj.mouseX;
oPoint.y = resizeObj.mouseY;
oPoint = this.localToGlobal(oPoint);
}
}
/**
* Clear the resizeObj and also set the latest position.
* @param The MouseEvent.MOUSE_UP
*/
private function oMouseUp(event:MouseEvent):void{
if(resizeObj != null){
initPosition(resizeObj);
}
resizeObj = null;
}
/**
* Show the mouse arrow when not draging.
* Call oResize(event) to resize window when mouse is inside the window area.
* @param The MouseEvent.MOUSE_MOVE
*/
private function oMouseMove(event:MouseEvent):void{
if(resizeObj == null){
var xPosition:Number = Application.application.parent.mouseX;
var yPosition:Number = Application.application.parent.mouseY;
if(xPosition >= (this.x + this.width - mouseMargin) && yPosition >= (this.y + this.height - mouseMargin)){
CursorUtil.changeCursor(leftObliqueSize, -6, -6);
mouseState = SIDE_RIGHT | SIDE_BOTTOM;
}else if(xPosition <= (this.x + mouseMargin) && yPosition <= (this.y + mouseMargin)){
CursorUtil.changeCursor(leftObliqueSize, -6, -6);
mouseState = SIDE_LEFT | SIDE_TOP;
}else if(xPosition <= (this.x + mouseMargin) && yPosition >= (this.y + this.height - mouseMargin)){
CursorUtil.changeCursor(rightObliqueSize, -6, -6);
mouseState = SIDE_LEFT | SIDE_BOTTOM;
}else if(xPosition >= (this.x + this.width - mouseMargin) && yPosition <= (this.y + mouseMargin)){
CursorUtil.changeCursor(rightObliqueSize, -6, -6);
mouseState = SIDE_RIGHT | SIDE_TOP;
}else if(xPosition >= (this.x + this.width - mouseMargin)){
CursorUtil.changeCursor(horizontalSize, -9, -9);
mouseState = SIDE_RIGHT;
}else if(xPosition <= (this.x + mouseMargin)){
CursorUtil.changeCursor(horizontalSize, -9, -9);
mouseState = SIDE_LEFT;
}else if(yPosition >= (this.y + this.height - mouseMargin)){
CursorUtil.changeCursor(verticalSize, -9, -9);
mouseState = SIDE_BOTTOM;
}else if(yPosition <= (this.y + mouseMargin)){
CursorUtil.changeCursor(verticalSize, -9, -9);
mouseState = SIDE_TOP;
}else{
mouseState = SIDE_OTHER;
CursorUtil.changeCursor(null, 0, 0);
}
}
//Use SystemManager to listen the mouse reize event, so we needn't handle the event at the current object.
//oResize(event);
}
/**
* Hide the arrow when not draging and moving out the window.
* @param The MouseEvent.MOUSE_MOVE
*/
private function oMouseOut(event:MouseEvent):void{
if(resizeObj == null){
CursorUtil.changeCursor(null, 0, 0);
}
}
/**
* Resize when the draging window, resizeObj is not null.
* @param The MouseEvent.MOUSE_MOVE
*/
private function oResize(event:MouseEvent):void{
if(resizeObj != null){
resizeObj.stopDragging();
var xPlus:Number = Application.application.parent.mouseX - resizeObj.oPoint.x;
var yPlus:Number = Application.application.parent.mouseY - resizeObj.oPoint.y;
switch(mouseState){
case SIDE_RIGHT | SIDE_BOTTOM:
resizeObj.width = resizeObj.oWidth + xPlus > _windowMinSize ? resizeObj.oWidth + xPlus : _windowMinSize;
resizeObj.height = resizeObj.oHeight + yPlus > _windowMinSize ? resizeObj.oHeight + yPlus : _windowMinSize;
break;
case SIDE_LEFT | SIDE_TOP:
resizeObj.x = xPlus < resizeObj.oWidth - _windowMinSize ? resizeObj.oX + xPlus: resizeObj.x;
resizeObj.y = yPlus < resizeObj.oHeight - _windowMinSize ? resizeObj.oY + yPlus : resizeObj.y;
resizeObj.width = resizeObj.oWidth - xPlus > _windowMinSize ? resizeObj.oWidth - xPlus : _windowMinSize;
resizeObj.height = resizeObj.oHeight - yPlus > _windowMinSize ? resizeObj.oHeight - yPlus : _windowMinSize;
break;
case SIDE_LEFT | SIDE_BOTTOM:
resizeObj.x = xPlus < resizeObj.oWidth - _windowMinSize ? resizeObj.oX + xPlus: resizeObj.x;
resizeObj.width = resizeObj.oWidth - xPlus > _windowMinSize ? resizeObj.oWidth - xPlus : _windowMinSize;
resizeObj.height = resizeObj.oHeight + yPlus > _windowMinSize ? resizeObj.oHeight + yPlus : _windowMinSize;
break;
case SIDE_RIGHT | SIDE_TOP:
resizeObj.y = yPlus < resizeObj.oHeight - _windowMinSize ? resizeObj.oY + yPlus : resizeObj.y;
resizeObj.width = resizeObj.oWidth + xPlus > _windowMinSize ? resizeObj.oWidth + xPlus : _windowMinSize;
resizeObj.height = resizeObj.oHeight - yPlus > _windowMinSize ? resizeObj.oHeight - yPlus : _windowMinSize;
break;
case SIDE_RIGHT:
resizeObj.width = resizeObj.oWidth + xPlus > _windowMinSize ? resizeObj.oWidth + xPlus : _windowMinSize;
break;
case SIDE_LEFT:
resizeObj.x = xPlus < resizeObj.oWidth - _windowMinSize ? resizeObj.oX + xPlus: resizeObj.x;
resizeObj.width = resizeObj.oWidth - xPlus > _windowMinSize ? resizeObj.oWidth - xPlus : _windowMinSize;
break;
case SIDE_BOTTOM:
resizeObj.height = resizeObj.oHeight + yPlus > _windowMinSize ? resizeObj.oHeight + yPlus : _windowMinSize;
break;
case SIDE_TOP:
resizeObj.y = yPlus < resizeObj.oHeight - _windowMinSize ? resizeObj.oY + yPlus : resizeObj.y;
resizeObj.height = resizeObj.oHeight - yPlus > _windowMinSize ? resizeObj.oHeight - yPlus : _windowMinSize;
break;
}
}
}
//--------------------------------------------------------------------------
//
// Control the window buttons.
//
//--------------------------------------------------------------------------
private var windowMinButton:Button;
private var windowMaxButton:Button;
private var windowCloseButton:Button;
[Embed(source="/sjd/assets/WindowMinButton.gif")]
private var windowMinButtonImg:Class;
[Embed(source="/sjd/assets/WindowMinButton2.gif")]
private var windowMinButtonImg2:Class;
[Embed(source="/sjd/assets/WindowMaxButton.gif")]
private var windowMaxButtonImg:Class;
[Embed(source="/sjd/assets/WindowMaxButton2.gif")]
private var windowMaxButtonImg2:Class;
[Embed(source="/sjd/assets/WindowCloseButton.gif")]
private var windowCloseButtonImg:Class;
[Embed(source="/sjd/assets/WindowCloseButton2.gif")]
private var windowCloseButtonImg2:Class;
/**
* Add the window buttons and layout them.
* @param The FlexEvent.CREATION_COMPLETE
*/
private function addButton(event:FlexEvent):void{
if(_showWindowButtons){
if(windowMinButton == null){
windowMinButton = new Button();
windowMinButton.width=10;
windowMinButton.height=10;
windowMinButton.focusEnabled=false;
windowMinButton.setStyle("upSkin", windowMinButtonImg);
windowMinButton.setStyle("overSkin", windowMinButtonImg2);
windowMinButton.setStyle("downSkin", windowMinButtonImg2);
windowMinButton.addEventListener(MouseEvent.CLICK, windowMinButton_clickHandler);
titleBar.addChild(windowMinButton);
}
if(windowMaxButton == null){
windowMaxButton = new Button();
windowMaxButton.width=10;
windowMaxButton.height=10;
windowMaxButton.focusEnabled=false;
windowMaxButton.setStyle("upSkin", windowMaxButtonImg);
windowMaxButton.setStyle("overSkin", windowMaxButtonImg2);
windowMaxButton.setStyle("downSkin", windowMaxButtonImg2);
windowMaxButton.addEventListener(MouseEvent.CLICK, windowMaxButton_clickHandler);
titleBar.addChild(windowMaxButton);
}
if(windowCloseButton == null){
windowCloseButton = new Button();
windowCloseButton.width=10;
windowCloseButton.height=10;
windowCloseButton.focusEnabled=false;
windowCloseButton.setStyle("upSkin", windowCloseButtonImg);
windowCloseButton.setStyle("overSkin", windowCloseButtonImg2);
windowCloseButton.setStyle("downSkin", windowCloseButtonImg2);
windowCloseButton.addEventListener(MouseEvent.CLICK, windowCloseButton_clickHandler);
titleBar.addChild(windowCloseButton);
}
layoutWindowButtons();
}else{
titleBar.removeChild(windowMinButton);
windowMinButton = null;
titleBar.removeChild(windowMaxButton);
windowMaxButton = null;
titleBar.removeChild(windowCloseButton);
windowCloseButton = null;
}
}
private function windowMinButton_clickHandler(event:MouseEvent):void{
dispatchEvent(new FlexEvent("minWindow"));
}
private function windowMaxButton_clickHandler(event:MouseEvent):void{
dispatchEvent(new FlexEvent("maxWindow"));
}
private function windowCloseButton_clickHandler(event:MouseEvent):void{
dispatchEvent(new FlexEvent("closeWindow"));
}
private function layoutWindowButtons():void{
if(windowMinButton != null){
windowMinButton.move(titleBar.width - 10 * 3 - 6 - 6 - 6, (titleBar.height - 10) / 2);
}
if(windowMaxButton != null){
windowMaxButton.move(titleBar.width - 10 * 2 - 6 - 6, (titleBar.height - 10) / 2);
}
if(windowCloseButton != null){
windowCloseButton.move(titleBar.width - 10 - 6, (titleBar.height - 10) / 2);
}
}
override protected function layoutChrome(unscaledWidth:Number, unscaledHeight:Number):void{
super.layoutChrome(unscaledWidth, unscaledHeight);
layoutWindowButtons();
}
}
}
一个工具类(可以将其并入到ResizeTitleWindow.as中)
package sjd.utils
{
import mx.managers.CursorManager;
import mx.managers.CursorManagerPriority;
/**
* @class CursorUtil
* @brief Set the cursor image
* @author Jove
* @version 1.0
*/
public class CursorUtil{
private static var currentType:Class = null;
/**
* Remove the current cursor and set an image.
* @param type The image class
* @param xOffset The xOffset of the cursorimage
* @param yOffset The yOffset of the cursor image
*/
public static function changeCursor(type:Class, xOffset:Number = 0, yOffset:Number = 0):void{
if(currentType != type){
currentType = type;
CursorManager.removeCursor(CursorManager.currentCursorID);
if(type != null){
CursorManager.setCursor(type, CursorManagerPriority.MEDIUM, xOffset, yOffset);
}
}
}
}
}
一个自定义的视图类:xxxView.mxml,也即使用ResizeWindow的类
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:mywindow="sjd.containers.*">
<mx:Script>
<![CDATA[
import mx.controls.TextInput;
import mx.containers.FormItem;
import mx.containers.Form;
import mx.controls.Alert;
import sjd.containers.ResizeWindow;
private function initApp():void{
var window:ResizeWindow = new ResizeWindow();
var form:Form = new Form();
var formItem1:FormItem = new FormItem();
formItem1.label = "事件源";
var text:TextInput = new TextInput();
formItem1.addChild(text);
form.addChild(formItem1);
//form.width = window.width * 0.2;
window.addChild(form);
}
//var window:ResizeWindow = new ResizeWindow();
private function closeWindowHandler():void{
win.height = 100;
win.width = 100;
}
private function minWindowHandler():void{
win.height = 200;
win.width = 200;
}
private function maxWindowHandler():void{
var window:ResizeWindow = new ResizeWindow();
win.height = 400;
win.width = 400;
}
]]>
</mx:Script>
<mywindow:ResizeWindow height="200" width="200" x="100" y="100" id="win"
closeWindow="closeWindowHandler()" maxWindow="maxWindowHandler()" minWindow="minWindowHandler()"/>
</mx:Application>
问题: 当向改装后的lsyTitleWindow使用addChild(Flex3)或者addElement(Flex4)方法添加组件时如何控制所添加的控件相对于LsyTitleWindow的位置。 你会发现你预先设置的
我所知道的有两种方式:
第一种(我现在所使用的):
就是预先在LsyTitleWindow中设置某个空间如Group,然后调整此Group在整个LsyTtileWindow中的位置,并且将其visialbe属性置为false; 当添加新控件时就将新控件放置在Group所在的范围内并同时将Group的visiable属性置为true。
这种方式我把它称之为黔驴技穷式(当时项目中要使用我就只想到了这种)
第二种:从网上学到的使用UpdateDisplayList
推荐一个不错的参考资料:
参考百度文库中的
《ActionScript开发高级可视化组件》
文章末尾附上了个人从网上搜索到的一些参考资料,资料中也提供了实现方案,大家若是需要的话就下载自行研究。
MDI组件.rar(googlecode中的flex-lib开源项目)
Jpane.rar