7yue's Weblog

Thinking in RIA Solutions...2470,8514,1020的生活演绎

« 使用AS3和FlashCS4的开发者必看的一本书祝各位圣诞和新年快乐 »

Flash Streaming Tool源代码

这篇文章是将我的Flash Streaming Tool的源代码开放。此小工具没有使用任何应用框架,可以按照方法区分功能,代码很容易看懂。我就不放zip出来了,防止懒人懒到什么都不改,直接就放到其他某个应用中去。再懒也要ctrl-C一下,:D. 另外,还有几个发现的bug没有fix,还有功能有待加强,有兴趣的就自己改进吧
主体程序fms7yue.mxml:

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="820" height="650" borderColor="#000000" creationComplete="setup()" title="Flash Streaming Tool">
  <mx:Style source="css/main.css"/>
  <mx:Script source="ConnectionManager.as"/>
      <mx:Script>
      <![CDATA[
        import com.zerlot.utils.OsDetection;
        import net.hires.utils.Stats;
        private var play_video:Video;
        private var os:OsDetection;
        private function setup():void{
          play_video=new Video();
          trace(play_video.width);
          trace(play_video.height);
          trace(this);
          trace(this.width);
          trace(bgcanvas.x);
          trace(bgcanvas.y);
          this.bgcanvas.rawChildren.addChildAt(play_video,1);
          bgcanvas.width=play_video.width;
          bgcanvas.height=play_video.height;
          this.play_video.x=0;
          this.play_video.y=0;
          addChildAt(new Stats(),0);
          os=new OsDetection();
          this.addEventListener(NativeDragEvent.NATIVE_DRAG_ENTER,onDragEnter,false,0,true);
          this.addEventListener(NativeDragEvent.NATIVE_DRAG_DROP,onDragDrop,false,0,true);
          //this.invalidateDisplayList();
        }
        private function onChangehttp():void{
          filetype.text="URL";
          myrtmpurl.editable=false;
          filepathname.text="http://domain/folder/.../*.flv";
          myrtmpurl.visible=false;
          rtmptitle.text="";
          live_cb.visible=false;
          live_cb.selected=false;
        }
        private function onChangertmp():void{
          rtmptitle.text="RTMP URL";
          filetype.text="Stream";
          myrtmpurl.editable=true;
          myrtmpurl.visible=true;
          filepathname.text="sample";
          live_cb.visible=true;
        }
      ]]>
  </mx:Script>
  <mx:TextInput x="70" y="313" width="265" id="myrtmpurl" text="rtmp://hostname:port/application/instance"/>
  <mx:Label x="10" y="316" text="RTMP URL" id="rtmptitle"/>
  <mx:Panel x="366" y="13" width="429" height="578" layout="absolute" title="Streaming状态信息" styleName="mypanelTitle">
    <mx:TextArea x="10" y="111" width="389" height="383" wordWrap="true" editable="false" enabled="true" id="FMS_Status"/>
    <mx:Button x="308" y="502" label="保存到文件" id="saveoutput_btn" click="onSavefile()"/>
    <mx:Button x="230" y="502" label="清除" width="70" id="clearstatus_btn" click="clearHistory()"/>
    <mx:ProgressBar id="progress_bar" themeColor="#271FC9"
            minimum="0" visible="true" maximum="100" label="当前播放进度 %3%%" 
            direction="right" mode="manual" width="389" labelPlacement="center" x="10" y="5"/>
    <mx:ProgressBar id="buffer_bar" themeColor="#F20D7A"
           minimum="0" visible="true" maximum="100" label="当前缓冲进度 %3%%" 
           direction="right" mode="manual" width="389" labelPlacement="center" y="28" x="10"/>
    <mx:Label x="43" y="503" text="©2008 www.7yue.com" fontSize="14" color="black"/>
    <mx:Image x="10" y="495" source="assets/version/version.png"/>
    <mx:Text x="10" y="54" width="389" id="buffer_stats" color="#000000" text=""/>
  </mx:Panel>
  <mx:ComboBox x="70" y="355" width="79" editable="false" enabled="true" selectedIndex="0" id="media_type" change="changeMedia()">
    <mx:ArrayCollection>
         <mx:Object label="FLV" data="FLV"/>
         <mx:Object label="MP3" data="MP3"/>
         <mx:Object label="MP4" data="MP4"/>
         <mx:Object label="ID3" data="ID3"/>
      </mx:ArrayCollection>
  </mx:ComboBox>
  <mx:Label x="10" y="358" text="File Type"/>
  <mx:Label x="10" y="401" text="Stream" id="filetype"/>
  <mx:TextInput x="70" y="399" width="265" id="filepathname" text="sample" change="closeStream()"/>
  <mx:Label x="10" y="446" text="Buffer"/>
  <mx:Label x="10" y="496" text="Seek"/>
  <mx:TextInput x="70" y="444" width="79" id="buffertime" text="2"/>
  <mx:TextInput x="70" y="494" width="79" id="seektime"/>
  <mx:Button x="179" y="495" label="搜索" id="gotoseek" click="onSeek()"/>
  <mx:Button x="10" y="567" label="播放" id="fmsplay_btn" click="playBackVideo()"/>
  <mx:Button x="70" y="567" label="停止" id="fmsstop_btn" click="closeNC()"/>
  <mx:RadioButton x="10" y="535" label="流" id="video_method_stream" selected="true" color="#FFFFFF" click="onChangertmp()"/>
  <mx:RadioButton x="70" y="535" label="渐进下载" id="video_method_progressive" color="#FFFFFF" click="onChangehttp()"/>
  <mx:Label x="148" y="497" text="sec"/>
  <mx:CheckBox x="180" y="444" label="直播" id="live_cb" color="#FFFFFF"/>
  <mx:Canvas x="20" y="40" id="bgcanvas" borderStyle="solid" borderColor="white" borderThickness="1">
    <mx:CheckBox x="0" y="0" label="自动调整大小" id="autoSize" color="#FFFFFF" click="onChangeSize()"/>
  </mx:Canvas>
</mx:WindowedApplication>

ConnectionManager.as,非AS Class类型:

// ActionScript file
  import flash.desktop.ClipboardFormats;
  import flash.desktop.NativeDragManager;
  import flash.events.Event;
  import flash.events.NativeDragEvent;
  import flash.events.NetStatusEvent;
  import flash.filesystem.File;
  import flash.net.NetConnection;
  import flash.net.NetStream;
  
  private var my_nc:NetConnection;
  [Bindable]
  private var play_status:String="stop";
  private var in_ns:NetStream;
  private var checkUp:Object;
  private var currentBW:Number;
  private var streamObj:Object=new Object();
  private var logfile:File;
  private var video_duration:Number;
  private var video_width:Number;
  private var video_height:Number;
  private var progress:Object;

public function playBackVideo():void {
  // control path for pause/resume
  if (play_status == "play") {
    fmsplay_btn.label = "继续";
    play_status = "pause";
    in_ns.pause();
    return;
  } else if (play_status == "pause") {
    // play resume
    play_status = "play";
    fmsplay_btn.label = "暂停";
    in_ns.resume();
    return;
  }
  //trace(rtmpurl);
  createConnection();
}

private function createConnection():void{
  if(video_method_stream.selected){
    trace(video_method_stream.selected);
    my_nc=new NetConnection();
    my_nc.addEventListener(NetStatusEvent.NET_STATUS,checkConnect,false,0,true);
    my_nc.connect(myrtmpurl.text,"streaming");
    my_nc.client=new Client(FMS_Status);
    checkUp=new Object();
  }else if(video_method_progressive.selected){
    trace("test progressive");
    my_nc=new NetConnection();
    my_nc.addEventListener(NetStatusEvent.NET_STATUS,checkConnect,false,0,true);
    my_nc.connect(null,"progressive");
    my_nc.client=new Client(FMS_Status);
    checkUp=new Object();
  }
}

private function checkConnect(nse:NetStatusEvent):void{
    FMS_Status.text +="正在连接......"+"\n";
    FMS_Status.text += "NetConnection onStatus"+"\n";
    for (var i:String in nse.info) {
      FMS_Status.text +=i+" : "+nse.info[i]+"\n";
    }
    if (nse.info.code == "NetConnection.Connect.Success") {
      createStream(NetConnection(nse.target));
      trace(nse.target);
    }
}

private function createStream(nc:NetConnection):void{
  FMS_Status.text+="NetStream状况: "+"\n";
  in_ns=new NetStream(nc);
  in_ns.bufferTime=0.5;
  play_video.attachNetStream(in_ns);
  if (!live_cb.selected) {
    in_ns.play(filepathname.text,0);
  } else {
    in_ns.play(filepathname.text);
  }
  in_ns.addEventListener(NetStatusEvent.NET_STATUS,showStream);
}

private function showStream(nse:NetStatusEvent):void{
  for(var i:String in nse.info){
    FMS_Status.text+=i+": "+nse.info[i]+"\n";
  }
  if(nse.info.code=="NetStream.Play.Stop"){
    play_status="stop";
    fmsplay_btn.label="播放";
  }
  if(nse.info.code=="NetStream.Play.Start"){
    play_status="play";
    fmsplay_btn.label="暂停";
  }
  streamObj.onMetaData=onMetaDataHandler;
  streamObj.onPlayStatus=onPlayStatusHandler;
  in_ns.client=streamObj;
  progress=new Progressmanager(in_ns,buffer_stats,buffer_bar,video_duration,progress_bar);
}

private function onPlayStatusHandler(info:Object):void{
  for(var i:String in info){
    FMS_Status.text+=i+":"+info[i]+"\n";
  }
  if(info.code=="NetStream.Play.Complete"){
    play_status="stop";
    in_ns.close();
    fmsplay_btn.label="播放";
  }
}

private function onMetaDataHandler(info:Object):void{
  for (var i:String in info) {
      FMS_Status.text +=i+": "+info[i]+"\n";
    }
    video_duration = info.duration;

    if (autoSize.selected && info.width && info.height) {
      video_width = play_video.width;
      video_height = play_video.height;
      play_video.width = info.width;
      play_video.height = info.height;
    } else {
      video_width = info.width;
      video_height = info.height;
    }
    switch(info.videocodecid){
      case 2:
        FMS_Status.text+="本视频是Sorenson H.263格式.\n";
        break;
      case 3:
        FMS_Status.text+="本视频是Screen Video格式,只能支持FP7以上版本.\n";
        break;
      case 4:
        FMS_Status.text+="本视频是On2 VP6格式.\n";
        break;
      case 5:
        FMS_Status.text+="本视频是On2 VP6具备alpha通道格式.\n";
        break;
      default:
        break;
    }
    // 设定真实的Buffer时间
    // 可以动态的设置buffer时间
    in_ns.bufferTime=Number(buffertime.text);
}


private function closeStream():void{
  if(in_ns!=null){
  play_status="stop";
  in_ns.close();
  progress.setBufferStats(play_status);
  fmsplay_btn.label="播放";
  }else{
  return;
  }
}

private function closeNC():void{
  play_status="stop";
  my_nc.close();
  progress.setBufferStats(play_status);
  fmsplay_btn.label="播放";
  os=null;
}

private function clearHistory():void{
  FMS_Status.text="";
}

private function changeMedia():void{
  if(media_type.selectedItem.data == "MP3"){
    filepathname.text = "mp3:";
  }else if (media_type.selectedItem.data == "ID3"){
    filepathname.text = "id3:";
  }else if (media_type.selectedItem.data=="MP4"){
    filepathname.text = "mp4:";
  }else{
    filepathname.text="";
  }
}

private function onSeek():void{
  in_ns.seek(Number(seektime.text));
}

private function onSavefile():void{
  //logfile=File.applicationStorageDirectory;
  //logfile=logfile.resolvePath("logs/");
  //trace(logfile.url);
  var dir:File =File.applicationDirectory;
  //dir.resolvePath("logs");
  trace(dir.url);
  var docsDir:File = File.documentsDirectory;
  try
  {
      docsDir.browseForSave("Save as:");
      docsDir.addEventListener(Event.SELECT, saveData);
  }
  catch (error:Error)
  {
      trace("Failed:", error.message)
  }
  //dir.addEventListener(Event.SELECT, dirSelected);
  //logfile.browseForDirectory("Select a directory");
}

private function saveData(event:Event):void{
      var newFile:File = event.target as File;
      var str:String = FMS_Status.text;
      var stream:FileStream = new FileStream();
      stream.open(newFile, FileMode.WRITE);
      stream.writeUTFBytes(str);
      stream.close();
}

private function onChangeSize():void{
  if(video_height != 0 && video_width != 0) {
    var temp_w:Number = play_video.width;
    var temp_h:Number = play_video.height;
    play_video.width = video_width;
    play_video.height = video_height;
    video_width = temp_w;
    video_height = temp_h;
  }
}
// Drag and Drop feature

private function onDragEnter(nde:NativeDragEvent):void{
  var dragFile:Object=nde.clipboard.getData(ClipboardFormats.FILE_LIST_FORMAT);
  trace(dragFile[0].name);
  if (dragFile[0].extension=="flv" || dragFile[0].extension == "mov" || dragFile[0].extension == "mp4" || dragFile[0].extension== "mp3"){
    NativeDragManager.acceptDragDrop(this);
  }
}

private function onDragDrop(nde:NativeDragEvent):void{
  var dragFile:Object=nde.clipboard.getData(ClipboardFormats.FILE_LIST_FORMAT);
  trace(dragFile[0].url);
  video_method_progressive.selected=true;
  onChangehttp();
  filepathname.text=dragFile[0].url;
}


Client.as,AS Class文件,带宽检测部分:

//如果FMS服务器端Application.xml的<BandwidthDetection enabled="true">,那么必须客户端包含以下代码
package
{
  import mx.controls.TextArea;
  
  internal class Client{
  private var currentBW:Number;
  private var checkUp:Object;
  private var fms_obj:TextArea;
  public function Client(fms:TextArea){
    fms_obj=fms;
  }
    public function onBWCheck(... rest):Number {
         return 0;
      }
  public function onBWDone(... rest):void {
         if (rest.length>0) {
            currentBW=rest[0];
           // currentBW=nc.client.sendInfo();
            trace("你的带宽速度是: "+currentBW +" Kbps.");
      //FMS_Status.text+="你的带宽速度是: "+currentBW +" Kbps.\n"
            trace("大约等于 "+Math.round(currentBW/1000)+ " Megabits每秒.");
      //FMS_Status.text+="大约等于 "+Math.round(currentBW/1000)+ " Megabits每秒.\n"
      fms_obj.text+="当前连接该FMS带宽速度是:"+currentBW +" Kbps.\n";
      fms_obj.text+="大约等于 "+Math.round(currentBW/1000)+ " Megabits每秒.\n";
      trace(fms_obj.text);
         }
      }
  }
}


Progressmanager.as,AS类文件,计算流长度和表象化:

//动态显示Progresss进度
package
{
  import flash.events.TimerEvent;
  import flash.net.NetStream;
  import flash.utils.Timer;
  
  import mx.controls.ProgressBar;
  import mx.controls.Text;
    
  public class Progressmanager
  {
    private var _in_ns_obj:NetStream;
    private var _buff_stats_obj:Text;
    private var _play_status_str:String;
    private var mytimer:Timer;
    private var _buff_bar_obj:ProgressBar;
    private var _progress_bar_obj:ProgressBar;
    private var _video_duration_num:Number;
    
    public function Progressmanager(ns:NetStream,ti:Text,bb:ProgressBar,vd:Number,pb:ProgressBar)
    {
      mytimer=new Timer(100,0);
      _in_ns_obj=ns;
      _buff_stats_obj=ti;
      //_play_status_str=ps;
      _buff_bar_obj=bb;
      _video_duration_num=vd;
      _progress_bar_obj=pb;
      mytimer.addEventListener(TimerEvent.TIMER,onTimer);
      mytimer.start();
    }
    
    private function onTimer(te:TimerEvent):void{
      //设定播放缓存
      var buffer:Number = Math.min(Math.round(_in_ns_obj.bufferLength/_in_ns_obj.bufferTime*100), 100);
      if(!isNaN(_in_ns_obj.bufferLength)){
      _buff_stats_obj.text= "当前Cache: "+_in_ns_obj.bufferLength+"    填充百分比:"+buffer+"%"+"    实时FPS: "+Math.round(_in_ns_obj.currentFPS*100)/100;
      }
      _buff_bar_obj.setProgress(buffer,100);
      //设定播放进度
      var preloadpercentage:Number=_in_ns_obj.time/_video_duration_num*100;
      _progress_bar_obj.setProgress(preloadpercentage,100);
      if (buffer == 0 && _in_ns_obj.currentFPS==0) {
        mytimer.stop();
        _progress_bar_obj.setProgress(0,100);
      }
    }
    
    public function setBufferStats(ps:String):void{
      _play_status_str=ps;
      mytimer.stop();
      if(_play_status_str=="stop"){
        _progress_bar_obj.setProgress(0,100);
        _buff_stats_obj.text="";
      }else{
      return;
      }
    }
  }
}

加入的Hi-ReS! Stas v.13代码,并做修改后的Stats.as,改了哪里,请自行查看

/**
 * Hi-ReS! Stats v1.3
 * 
 * Released under MIT license:
 * http://www.opensource.org/licenses/mit-license.php
 *  
 * How to use:
 * 
 *   addChild( new Stats() );
 * 
 * version log:
 *
 *  08.07.12    1.3    Mr.doob      + Some speed and code optimisations
 *  08.02.15    1.2    Mr.doob      + Class renamed to Stats (previously FPS)
 *  08.01.05    1.2    Mr.doob      + Click changes the fps of flash (half up increases,
 *                    half down decreases)
 *  08.01.04    1.1    Mr.doob & Theo    + Log shape for MEM
 *                   + More room for MS
 *                   + Shameless ripoff of Alternativa's FPS look ;)
 *   07.12.13    1.0    Mr.doob      + First version
 **/

package net.hires.utils
{
  import flash.display.Bitmap;
  import flash.display.BitmapData;
  import flash.events.Event;
  import flash.events.MouseEvent;
  import flash.geom.Rectangle;
  import flash.system.System;
  import flash.text.TextField;
  import flash.text.TextFormat;
  import flash.utils.getTimer;
  
  import mx.core.UIComponent;
  
  public class Stats extends UIComponent
  {    
    private var graph : BitmapData;
    
    private var fpsText : TextField, msText : TextField, memText : TextField, format : TextFormat;
    
    private var fps :int, timer : int, ms : int, msPrev  : int = 0;
    private var mem : Number = 0;

    public function Stats( ):void
    {
      graph = new BitmapData( 60, 35, false, 0x000000 );
      var gBitmap:Bitmap = new Bitmap( graph );
      gBitmap.x= 60;
      gBitmap.y = 0;
      gBitmap.alpha
      addChild(gBitmap);
    
      format = new TextFormat( "_sans", 9 );

      
      fpsText = new TextField();
      msText = new TextField();
      memText = new TextField();
      
      fpsText.defaultTextFormat = msText.defaultTextFormat = memText.defaultTextFormat = format;
      fpsText.width = msText.width = memText.width = 60;
      fpsText.selectable = msText.selectable = memText.selectable = false;
      
      fpsText.textColor = 0xFFFF00;
      fpsText.text = "fps: ";
      addChild(fpsText);
      
      msText.y = 10;
      msText.textColor = 0x00FF00;
      msText.text = "ms: ";
      addChild(msText);

      memText.y = 20;
      memText.textColor = 0x00FFFF;
      memText.text = "mem: ";
      addChild(memText);
      
      addEventListener(MouseEvent.CLICK, mouseHandler);
      addEventListener(Event.ENTER_FRAME, update);
    }
    
    private function mouseHandler( e:MouseEvent ):void
    {
      if (this.mouseY > this.height * .35)
        stage.frameRate --;
      else
        stage.frameRate ++;
        
      fpsText.text = "fps: " + fps + " / " + stage.frameRate;
    }  
    
    private function update( e:Event ):void
    {
      timer = getTimer();
      fps++;
      
      if( timer - 1000 > msPrev )
      {
        msPrev = timer;
        mem = Number( ( System.totalMemory / 1048576 ).toFixed(3) );
        
        var fpsGraph : int = Math.min( 50, 50 / stage.frameRate * fps );
        var memGraph:Number =  Math.min( 50, Math.sqrt( Math.sqrt( mem * 5000 ) ) ) - 2;
        
        graph.scroll( 1, 0 );
        graph.fillRect( new Rectangle( 0, 0, 1, graph.height ), 0x000000 );
        graph.setPixel( 0, graph.height - fpsGraph, 0xFFFF00);
        graph.setPixel( 0, graph.height - ( ( timer - ms ) >> 1 ), 0x00FF00 );        
        graph.setPixel( 0, graph.height - memGraph, 0x00FFFF);
        
        fpsText.text = "fps: " + fps + " / " + stage.frameRate;
        memText.text = "mem: " + mem;
        
        fps = 0;
      }
      
      msText.text = "ms: " + (timer - ms);
      ms = timer;
    }
  }
}

没有进一步图形化的系统检测部分OsDetection.as, AS Class类型,有兴趣请自行增强此部分功能吧:

package com.zerlot.utils
{
  import flash.system.Capabilities;
  public class OsDetection
  {
    public function OsDetection()
    {
      showCapabilites();
    }
    private function showCapabilites():void{
      trace("对用户的摄像头和麦克风的访问是已经通过管理方式禁止:" + Capabilities.avHardwareDisable);

            trace("系统是否支持与辅助功能通信: " + Capabilities.hasAccessibility);

            trace("系统是否有音频功能: " + Capabilities.hasAudio);

            trace("系统是否可以对音频流进行编码: " + Capabilities.hasAudioEncoder);

            trace("系统是否支持嵌入的视频: " + Capabilities.hasEmbeddedVideo);

            trace("系统是否具有 MP3 解码器: " + Capabilities.hasMP3);

            trace("系统是否支持打印: " + Capabilities.hasPrinting);

            trace("系统是否支持开发通过 Flash Media Server 运行的屏幕广播应用程序: " + Capabilities.hasScreenBroadcast);

            trace("系统是否支持回放通过 Flash Media Server 运行的屏幕广播应用程序: " + Capabilities.hasScreenPlayback);

            trace("系统是否可以播放音频流: " + Capabilities.hasStreamingAudio);

            trace("系统是否可以对视频流例如来自 Web 摄像头的视频流进行编码: " + Capabilities.hasVideoEncoder);

            trace("系统是特殊的Flash Player调试版本: " + Capabilities.isDebugger);

            trace("行内容的系统的语言代码: " + Capabilities.language);

            trace("对用户硬盘的读取权限是已经通过管理方式禁止: " + Capabilities.localFileReadDisable);

            trace("指定 Flash Player 的运行版本或 AIR 运行时的制造商: " + Capabilities.manufacturer);

            trace("当前的操作系统: " + Capabilities.os);

            trace("屏幕的像素高宽比: " + Capabilities.pixelAspectRatio);

            trace("运行时环境的类型: " + Capabilities.playerType);

            trace("屏幕的每英寸点数dpi分辨率: " + Capabilities.screenDPI);

            trace("屏幕的最大水平分辨率: " + Capabilities.screenResolutionX);

            trace("屏幕的最大垂直分辨率: " + Capabilities.screenResolutionY);

            trace("Flash Player 或 Adobe® AIR 平台和版本信息: " + Capabilities.version);

    }
  }
}

AIR1.5配置文件fms7yue-app.xml:

<?xml version="1.0" encoding="UTF-8"?>
<application xmlns="http://ns.adobe.com/air/application/1.5">

  <!-- The application identifier string, unique to this application. Required. -->
  <id>fms7yue</id>

  <!-- Used as the filename for the application. Required. -->
  <filename>fms7yue</filename>

  <!-- The name that is displayed in the AIR application installer. Optional. -->
  <name>
    <text xml:lang="zh_CN">Flash流媒体工具</text>
  </name>

  <!-- An application version designator (such as "v1", "2.5", or "Alpha 1"). Required. -->
  <version>v1.1 r03</version>

  <!-- Description, displayed in the AIR application installer. Optional. -->
  <description>
    <text xml:lang="zh_CN">Flash Streaming Tool v1.1 r03支持Http/RTMP方式流媒体播放及相关检测的工具。安装后请参考安装路径下的README文件</text>
  </description>

  <!-- Copyright information. Optional -->
  <copyright>©2008 www.7yue.com</copyright>

  <!-- Settings for the application's initial window. Required. -->
  <initialWindow>
    <!-- The main SWF or HTML file of the application. Required. -->
    <!-- Note: In Flex Builder, the SWF reference is set automatically. -->
    <content>fms7yue.swf</content>
    
    <!-- The title of the main window. Optional. -->
    <title>Flash Streaming Tool 1.1 r03</title>

    <!-- The type of system chrome to use (either "standard" or "none"). Optional. Default standard. -->
    <systemChrome>none</systemChrome>

    <!-- Whether the window is transparent. Only applicable when systemChrome is false. Optional. Default false. -->
    <transparent>true</transparent>

    <!-- Whether the window is initially visible. Optional. Default false. -->
    <visible>true</visible>

    <!-- Whether the user can minimize the window. Optional. Default true. -->
    <minimizable>true</minimizable>

    <!-- Whether the user can maximize the window. Optional. Default true. -->
    <maximizable>false</maximizable>

    <!-- Whether the user can resize the window. Optional. Default true. -->
    <resizable>false</resizable>

    <!-- The window's initial width. Optional. 
    <width></width>-->

    <!-- The window's initial height. Optional. 
     <height></height>-->

    <!-- The window's initial x position. Optional. -->
    <!-- <x></x> -->

    <!-- The window's initial y position. Optional. -->
    <!-- <y></y> -->

    <!-- The window's minimum size, specified as a width/height pair, such as "400 200". Optional. -->
    <!-- <minSize></minSize> -->

    <!-- The window's initial maximum size, specified as a width/height pair, such as "1600 1200". Optional. -->
    <!-- <maxSize></maxSize> -->
  </initialWindow>

  <!-- The subpath of the standard default installation location to use. Optional. -->
  <!-- <installFolder></installFolder> -->

  <!-- The subpath of the Windows Start/Programs menu to use. Optional. -->
  <!-- <programMenuFolder></programMenuFolder> -->

  <!-- The icon the system uses for the application. For at least one resolution,
     specify the path to a PNG file included in the AIR package. Optional. -->
  <icon>
    <image16x16>assets/icon_016.png</image16x16>
    <image32x32>assets/icon_032.png</image32x32>
    <image48x48>assets/icon_048.png</image48x48>
    <image128x128>assets/icon_128.png</image128x128>
  </icon>

  <!-- Whether the application handles the update when a user double-clicks an update version
  of the AIR file (true), or the default AIR application installer handles the update (false).
  Optional. Default false. -->
  <!-- <customUpdateUI></customUpdateUI> -->
  
  <!-- Whether the application can be launched when the user clicks a link in a web browser.
  Optional. Default false. -->
  <!-- <allowBrowserInvocation></allowBrowserInvocation> -->

  <!-- Listing of file types for which the application can register. Optional. -->
  <!-- <fileTypes> -->

    <!-- Defines one file type. Optional. -->
    <!-- <fileType> -->

      <!-- The name that the system displays for the registered file type. Required. -->
      <!-- <name></name> -->

      <!-- The extension to register. Required. -->
      <!-- <extension></extension> -->
      
      <!-- The description of the file type. Optional. -->
      <!-- <description></description> -->
      
      <!-- The MIME type. Optional. -->
      <!-- <contentType></contentType> -->
      
      <!-- The icon to display for the file type. Optional. -->
      <!-- <icon>
        <image16x16></image16x16>
        <image32x32></image32x32>
        <image48x48></image48x48>
        <image128x128></image128x128>
      </icon> -->
      
    <!-- </fileType> -->
  <!-- </fileTypes> -->

</application>

程序很小,功能有限,如果使用的朋友没有找到你们想要的功能,还望见谅。

  • quote 11.showping
  • http://showping.wordpress.com.cn/
  • 7yue兄:
    您好!
    我们公司购买了FMS3的无限制版,请问如何能联系到您?因为我们迫切需要一些技术支持。
    Admin7yue 于 2009-3-31 11:58:38 回复
    hello,请你联系公司销售,有销售工程师和售后支持。我已经不再管理FMS产品线。
  • 2009-3-31 9:52:48 回复该留言
  • quote 12.showping
  • 请问如何能联系到国内的销售工程师和今后支持?
    烦请告知!
  • 2009-3-31 15:21:43 回复该留言
  • quote 13.showping
  • 等了很久,也找了很久,都没有找到国内的销售工程师和售后支持的联系方式,郁闷啊郁闷
  • 2009-4-1 10:48:30 回复该留言

日历

最新评论及回复

最近发表

Powered By Z-Blog 1.8 Walle Build 91204

Copyright 2007 www.7yue.com. Some Rights Reserved.
京ICP备05064035号