守望者--AIR技术交流

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

搜索
热搜: ANE FlasCC 炼金术
查看: 3385|回复: 1

[Windows] 无需Flash Builder制作ane--windows截屏ane制作完全教程

[复制链接]
  • TA的每日心情
    擦汗
    2018-4-10 15:18
  • 签到天数: 447 天

    [LV.9]以坛为家II

    1742

    主题

    2094

    帖子

    13万

    积分

    超级版主

    Rank: 18Rank: 18Rank: 18Rank: 18Rank: 18

    威望
    562
    贡献
    29
    金币
    52584
    钢镚
    1422

    开源英雄守望者

    发表于 2014-12-30 22:24:05 | 显示全部楼层 |阅读模式
    如题~昨天研究了一下ane,现在打算给出一个比较详细的教程,就以截屏为例吧~^_^
    -----------------------------------------我是分割线--------------------------------------------------
    工具材料:Adobe Flash Professional CS6,Microsoft Visual Studio 2012 Express,windows 7/8,AIR3.7(其他版本一样)
    -----------------------------------------我是分割线--------------------------------------------------
    要做一个ane,我们围绕需要的东西来做:
    先看打包ane的命令行:
    adt -package -storetype pkcs12 -keystore mycert.p12 -keypass myPassword -target ane output.ane ext.xml -swc extension.swc -platform Windows-x86 extension.dll library.swf
    所以,我们需要:
    1.mycert.p12         证书文件
    2.extension.swc     swc文件
    3.extension.dll       dll文件
    4.library.swf           library.swf文件
    5.ext.xml               ane描述文件
    -----------------------------------------我是分割线--------------------------------------------------
    首先从extension.swc开始,也就是as端了~
    打开Flash Professional,新建一个AIR文件,命名为ScreenCapture.fla;新建一个ActionScript类,类名com.si2.ScreenCapture,
    将该类设置为AIR文件的文档类,注意文件夹层次:
    ScreenCapture.fla  ./ScreenCapture.fla
    ScreenCapture.as  ./com/si2/ScreenCapture.as
    在ScreenCapture.as中写上代码:

    1. package com.si2 {
    2.         import flash.display.MovieClip;
    3.         import flash.external.ExtensionContext;
    4.         import flash.display.BitmapData;
    5.         import flash.geom.Rectangle;
    6.         import flash.utils.ByteArray;
    7.         import flash.display.Screen;
    8.         //因为要使用Flash Professional打包为swc,所以必须继承自MovieClip
    9.         public class ScreenCapture extends MovieClip{

    10.                 //本类的拓展对象
    11.                 private var ext:ExtensionContext;
    12.                 public function ScreenCapture(){
    13.                         //构造时初始化拓展对象
    14.                         ext=ExtensionContext.createExtensionContext("com.si2.display.ScreenCapture","i");
    15.                 }
    16.                 public function captureScreen(rect:Rectangle=null):BitmapData{
    17.                         //根据rect(截屏范围)来确定需要传递给本机代码的参数
    18.                         var ba:ByteArray=new ByteArray();
    19.                         var w:int=rect?rect.width:Screen.mainScreen.bounds.width;
    20.                         var h:int=rect?rect.height:Screen.mainScreen.bounds.height;
    21.                         //字节数组的长度是像素数目*4(ARGB)
    22.                         ba.length=w*h*4;
    23.                         //将范围信息和ba作为参数传递给C语言的captureScreen函数
    24.                         //其中ba可以让本机端填充位图信息
    25.                         if(rect){
    26.                                 ext.call("captureScreen",rect.x,rect.y,w,h,ba);
    27.                         }else{
    28.                                 ext.call("captureScreen",0,0,w,h,ba);
    29.                         }
    30.                         //归零position,准备setPixels
    31.                         ba.position=0;
    32.                         var bmd:BitmapData=new BitmapData(w,h,false);
    33.                         bmd.setPixels(bmd.rect,ba);
    34.                         //大功告成
    35.                         return bmd;
    36.                 }

    37.         }
    38.         
    39. }
    复制代码
    然后回到AIR文件,打开文件-发布设置,勾选“发布swc”,确定




    回到flash,按下Ctrl+ENTER,这时文件夹里是不是出现了ScreenCapture.swc?这就是我们想要的~




    留着备用
    -----------------------------------------我是分割线--------------------------------------------------
    接下来,取得library.swf文件,从swc中提取
    复制一份swc的副本,把后缀改为zip,打开,看到了library.swf没?果断取之~




    接下来,就是关键部分啦,写本机端代码:
    打开Visual Studio 2012 Express,新建VC空项目,命名为ScreenCapture
    从Flash的安装文件夹获取FlashRuntimeExtension.h文件,复制到vC项目目录里面,/AIR3.7/include/FlashRuntimeExtensions.h
    从Flash的安装文件夹获取FlashRuntimeExtensions.lib文件,复制到vC项目目录里面,AIR3.7/lib/win/FlashRuntimeExtensions.lib
    在VC中新建源文件ScreenCapture.cpp
    现在目录如下:




    在ScreenCapture.cpp中写入一下代码:
    1. #include<Windows.h>
    2. #include"FlashRuntimeExtensions.h"

    3. #pragma comment(lib, "FlashRuntimeExtensions.lib")
    4. extern "C" __declspec(dllexport) FREObject captureScreen(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]);
    5. extern "C" __declspec(dllexport) void MyExtensionInitalizer(void** extDataToSet,FREContextInitializer* ctxInitializerToSet,FREContextFinalizer* ctxFinalizerToSet);
    6. extern "C" __declspec(dllexport) void ctxend(FREContext ctx);
    7. extern "C" __declspec(dllexport) void ctxinit(void* extData,const uint8_t* ctxType,FREContext ctx,uint32_t* numFunctionsToSet,const FRENamedFunction** functionsToSet);
    8. void MyExtensionInitalizer(void** extDataToSet,FREContextInitializer* ctxInitializerToSet,FREContextFinalizer* ctxFinalizerToSet){
    9.         extDataToSet=NULL;
    10.         *ctxInitializerToSet=&ctxinit;
    11.         *ctxFinalizerToSet=&ctxend;
    12. }
    13. void ctxinit(void* extData,const uint8_t* ctxType,FREContext ctx,uint32_t* numFunctionsToSet,const FRENamedFunction** functionsToSet){
    14.         *numFunctionsToSet=1;
    15.         FRENamedFunction* func=(FRENamedFunction*)malloc(sizeof(FRENamedFunction)*(*numFunctionsToSet));
    16.         func[0].name=(const uint8_t*)"captureScreen";
    17.         func[0].functionData=NULL;
    18.         func[0].function=&captureScreen;
    19.         *functionsToSet=func;
    20. }
    21. void ctxend(FREContext ctx){
    22.         
    23. }
    24. FREObject captureScreen(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]){
    25.         void _captureScreen(int x,int y,int width, int height,uint8_t* ba);
    26.         if (argc!=5) return NULL;
    27.         FREByteArray ba;
    28.         FREAcquireByteArray(argv[4],&ba);
    29.         int x,y,width,height;
    30.         FREGetObjectAsInt32(argv[0],&x);
    31.         FREGetObjectAsInt32(argv[1],&y);
    32.         FREGetObjectAsInt32(argv[2],&width);
    33.         FREGetObjectAsInt32(argv[3],&height);
    34.         ba.length=width*height*4;
    35.         _captureScreen(x,y,width,height,ba.bytes);
    36.         FREReleaseByteArray(argv[4]);
    37. }
    38. void _captureScreen(int x,int y,int width, int height,uint8_t* ba){
    39.         HDC hScreenDC = CreateDC("DISPLAY", NULL, NULL, NULL);
    40.         HDC hmemDC = CreateCompatibleDC(hScreenDC);
    41.         // 创建BTIMAP
    42.         HBITMAP hBitmap = CreateCompatibleBitmap(hScreenDC, width, height);
    43.         // 将BITMAP选择入内存DC。
    44.         HBITMAP hOldBM = (HBITMAP)SelectObject(hmemDC, hBitmap);
    45.         // BitBlt屏幕DC到内存DC,根据所需截取的获取设置参数
    46.         BitBlt(hmemDC, 0, 0, width, height, hScreenDC, x, y, SRCCOPY);
    47.         // 将旧的BITMAP对象选择回内存DC,返回值为被替换的对象,既所截取的位图
    48.         hBitmap = (HBITMAP)SelectObject(hmemDC, hOldBM);
    49.         // 位图数据大小
    50.         DWORD dwBitmapArraySize;
    51.         // 位图信息头
    52.         BITMAPINFO bmInfo;
    53.         PVOID lpvpxldata;
    54.         // 为位图数据申请内存空间
    55.         dwBitmapArraySize = ((((width*32) + 31) & ~31)>> 3)* height;
    56.         lpvpxldata = HeapAlloc(GetProcessHeap(),HEAP_NO_SERIALIZE,dwBitmapArraySize);
    57.         ZeroMemory(lpvpxldata,dwBitmapArraySize);

    58.         // 添充 BITMAPINFO 结构
    59.         ZeroMemory(&bmInfo,sizeof(BITMAPINFO));
    60.         bmInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    61.         bmInfo.bmiHeader.biWidth = width;
    62.         bmInfo.bmiHeader.biHeight = height;
    63.         bmInfo.bmiHeader.biPlanes = 1;
    64.         bmInfo.bmiHeader.biBitCount = 32;
    65.         bmInfo.bmiHeader.biCompression = BI_RGB;

    66.         GetDIBits(hmemDC, hBitmap, 0, bmInfo.bmiHeader.biHeight,lpvpxldata, &bmInfo, DIB_RGB_COLORS);
    67.         uint8_t* t=(uint8_t*)lpvpxldata;
    68.         for(int i=0;i<height;i++){
    69.                 for(int j=0;j<width;j++){
    70.                         ba[4*(i*width+j)+0]=t[4*((height-1-i)*width+j)+3];
    71.                         ba[4*(i*width+j)+1]=t[4*((height-1-i)*width+j)+2];
    72.                         ba[4*(i*width+j)+2]=t[4*((height-1-i)*width+j)+1];
    73.                         ba[4*(i*width+j)+3]=t[4*((height-1-i)*width+j)+0];
    74.                 }
    75.         }
    76.         HeapFree(GetProcessHeap(),HEAP_NO_SERIALIZE,lpvpxldata);
    77.         DeleteDC(hScreenDC);
    78.         DeleteDC(hmemDC);        
    79. }
    复制代码
    #这里建议大家不要用GetPixel函数从DC中取得像素,从内存DC中取得全屏像素然后写入Byte数组在我电脑上要1秒钟,但是用GETDIBits函数基本上顺时完成#
    然后MyExtensionInitalizer这个函数名可以随便取的,之后再描述文件里面告诉系统函数名称就好
    最后,注意用GETDIBits取出来的像素是从左下角到右上角的,而且像素排列时BGRA,跟Flash的正好相反,所以有了最后那个for循环“转正”

    好啦,代码写完了,现在配置工程属性(因为要发布dll而不是exe)
    打开VS的调试-ScreenCapture属性,选择“常规”,然后右边两项改为dll,确定,如图:




    回到主界面,然后点上方的“本地windows调试器”,之前做的正确的话,这里会弹出错误“无法执行ScreenCapture.dll”,这样就好了~
    现在回到VS工程目录/Debug下,有没有看到ScreenCapture.dll文件呢?看到了的话赶紧取之~,跟之前的Flash放在一起备用~
    -----------------------------------------我是分割线--------------------------------------------------
    接下来,我们来写ext.xml文件~
    新建一个文本文档:


    1. <extension xmlns="http://ns.adobe.com/air/extension/3.7">
    2.         <id>com.si2.display.ScreenCapture</id>
    3.         <versionNumber>0.0.1</versionNumber>
    4.         <platforms>
    5.                 <platform name="Windows-x86">
    6.                         <applicationDeployment>
    7.                                 <nativeLibrary>ScreenCapture.dll</nativeLibrary>
    8.                                 <initializer>MyExtensionInitalizer</initializer>
    9.                         </applicationDeployment>
    10.                 </platform>
    11.         </platforms>
    12. </extension>
    复制代码
    保存为ext.xml,注意上面的3.7要跟AIR的版本号一致~
    -----------------------------------------我是分割线--------------------------------------------------
    接下来,拿出我们的证书(没有的话自行百度之),myPercept.p12,跟之前的文件放到一起,现在我们攒齐了所有的文件了:




    -----------------------------------------我是分割线--------------------------------------------------
    再然后,就是使用adt来打包ane了:
    这里有两个方法,第一个是把AIRSDK下面的adt.bat复制到这个文件夹里面来,但是如果我们要打包很多ane的话就很麻烦,所以第二个方法是把AIRSDK的bin目录设置为系统的环境变量(不会设置可以百度)
    进入命令行,来到本目录,输入以下代码:
    1. adt -package -storetype pkcs12 -keystore mycert.p12 -keypass myPassword -target ane com.si2.ScreenCapture.aneext.xml -swc ScreenCapture.swc -platform Windows-x86 ScreenCapture.dll library.swf
    复制代码




    注意把myPassword替换成你证书的密码啊~
    回车,一切正常的话没有输出,文件夹下面出现了com.si2.ScreenCapture.ane文件了~
    大功告成!



    最后的最后,让我们来试验一下:
    新建一个AIR文件,打开文件-ActionScript设置,添加我们刚刚发布的ane:





    按F9打开代码行,输入:
    1. import com.si2.ScreenCapture;
    2. import flash.display.Bitmap;

    3. addChild(new Bitmap(new ScreenCapture().captureScreen()));
    复制代码
    接下来,就是见证奇迹的时刻了~
    按下Ctrl+ENTER
    是不是能看到你的屏幕显示在舞台上啦~

    大家有问题可以问哦= =欢迎交流学习~


    整个工程:C+AS放在这里了,需要的下:


    2013.7.25更新:
    上面那个成品ane今天在Adobe Flash CC里不知为何用不了了。。再上传一份CC里能用的成品~




    本文来自:

    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    守望者AIR技术交流社区(www.airmyth.com)
    回复

    使用道具 举报

  • TA的每日心情
    擦汗
    2018-4-10 15:18
  • 签到天数: 447 天

    [LV.9]以坛为家II

    1742

    主题

    2094

    帖子

    13万

    积分

    超级版主

    Rank: 18Rank: 18Rank: 18Rank: 18Rank: 18

    威望
    562
    贡献
    29
    金币
    52584
    钢镚
    1422

    开源英雄守望者

     楼主| 发表于 2014-12-30 23:05:44 | 显示全部楼层
    今天研究了ANE,进展还算比较顺利的,成功用C语言实现了截图的ANE,全屏截图返回BitmapData只需50ms,大大改善了几个需要截图的程序的易用性~
    使用方法,在ActionScript设置里面加入ane,然后就能使用了~
    示例代码:
    1. import com.si2.ScreenCapture;
    2. import flash.geom.Rectangle;
    3. import flash.display.Bitmap;

    4. ScreenCapture.init();
    5. addChild(new Bitmap(ScreenCapture.captureScreen(new Rectangle(0,0,500,400))));
    复制代码
    运行结果:




    放出ane:V0.0.1 修复内存泄露问题
    V0.0.2 降低所需AIR版本,3.4V0.0.3 改为静态类型,通过init方法初始化,取消了自MovieClip的继承




    不想花银子的我放到百度网盘上啦~~
    http://pan.baidu.com/share/link?shareid=492494&uk=3641178877

    教程已发~见开头

    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    守望者AIR技术交流社区(www.airmyth.com)
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    
    关闭

    站长推荐上一条 /4 下一条

    QQ|手机版|Archiver|网站地图|小黑屋|守望者 ( 京ICP备14061876号

    GMT+8, 2024-3-19 16:45 , Processed in 0.053932 second(s), 35 queries .

    守望者AIR

    守望者AIR技术交流社区

    本站成立于 2014年12月31日

    快速回复 返回顶部 返回列表