- 积分
- 136080
- 注册时间
- 2014-12-27
- 最后登录
- 2024-3-8
- 在线时间
- 602 小时
- 威望
- 562
- 贡献
- 29
- 金币
- 52584
- 钢镚
- 1422
- 交易凭证
- 1
- 分享
- 0
- 精华
- 33
- 帖子
- 2094
- 主题
- 1742
TA的每日心情 | 擦汗 2018-4-10 15:18 |
---|
签到天数: 447 天 [LV.9]以坛为家II
超级版主
- 威望
- 562
- 贡献
- 29
- 金币
- 52584
- 钢镚
- 1422
|
如题~昨天研究了一下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中写上代码:
- package com.si2 {
- import flash.display.MovieClip;
- import flash.external.ExtensionContext;
- import flash.display.BitmapData;
- import flash.geom.Rectangle;
- import flash.utils.ByteArray;
- import flash.display.Screen;
- //因为要使用Flash Professional打包为swc,所以必须继承自MovieClip
- public class ScreenCapture extends MovieClip{
- //本类的拓展对象
- private var ext:ExtensionContext;
- public function ScreenCapture(){
- //构造时初始化拓展对象
- ext=ExtensionContext.createExtensionContext("com.si2.display.ScreenCapture","i");
- }
- public function captureScreen(rect:Rectangle=null):BitmapData{
- //根据rect(截屏范围)来确定需要传递给本机代码的参数
- var ba:ByteArray=new ByteArray();
- var w:int=rect?rect.width:Screen.mainScreen.bounds.width;
- var h:int=rect?rect.height:Screen.mainScreen.bounds.height;
- //字节数组的长度是像素数目*4(ARGB)
- ba.length=w*h*4;
- //将范围信息和ba作为参数传递给C语言的captureScreen函数
- //其中ba可以让本机端填充位图信息
- if(rect){
- ext.call("captureScreen",rect.x,rect.y,w,h,ba);
- }else{
- ext.call("captureScreen",0,0,w,h,ba);
- }
- //归零position,准备setPixels
- ba.position=0;
- var bmd:BitmapData=new BitmapData(w,h,false);
- bmd.setPixels(bmd.rect,ba);
- //大功告成
- return bmd;
- }
- }
-
- }
复制代码 然后回到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中写入一下代码:
- #include<Windows.h>
- #include"FlashRuntimeExtensions.h"
- #pragma comment(lib, "FlashRuntimeExtensions.lib")
- extern "C" __declspec(dllexport) FREObject captureScreen(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]);
- extern "C" __declspec(dllexport) void MyExtensionInitalizer(void** extDataToSet,FREContextInitializer* ctxInitializerToSet,FREContextFinalizer* ctxFinalizerToSet);
- extern "C" __declspec(dllexport) void ctxend(FREContext ctx);
- extern "C" __declspec(dllexport) void ctxinit(void* extData,const uint8_t* ctxType,FREContext ctx,uint32_t* numFunctionsToSet,const FRENamedFunction** functionsToSet);
- void MyExtensionInitalizer(void** extDataToSet,FREContextInitializer* ctxInitializerToSet,FREContextFinalizer* ctxFinalizerToSet){
- extDataToSet=NULL;
- *ctxInitializerToSet=&ctxinit;
- *ctxFinalizerToSet=&ctxend;
- }
- void ctxinit(void* extData,const uint8_t* ctxType,FREContext ctx,uint32_t* numFunctionsToSet,const FRENamedFunction** functionsToSet){
- *numFunctionsToSet=1;
- FRENamedFunction* func=(FRENamedFunction*)malloc(sizeof(FRENamedFunction)*(*numFunctionsToSet));
- func[0].name=(const uint8_t*)"captureScreen";
- func[0].functionData=NULL;
- func[0].function=&captureScreen;
- *functionsToSet=func;
- }
- void ctxend(FREContext ctx){
-
- }
- FREObject captureScreen(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]){
- void _captureScreen(int x,int y,int width, int height,uint8_t* ba);
- if (argc!=5) return NULL;
- FREByteArray ba;
- FREAcquireByteArray(argv[4],&ba);
- int x,y,width,height;
- FREGetObjectAsInt32(argv[0],&x);
- FREGetObjectAsInt32(argv[1],&y);
- FREGetObjectAsInt32(argv[2],&width);
- FREGetObjectAsInt32(argv[3],&height);
- ba.length=width*height*4;
- _captureScreen(x,y,width,height,ba.bytes);
- FREReleaseByteArray(argv[4]);
- }
- void _captureScreen(int x,int y,int width, int height,uint8_t* ba){
- HDC hScreenDC = CreateDC("DISPLAY", NULL, NULL, NULL);
- HDC hmemDC = CreateCompatibleDC(hScreenDC);
- // 创建BTIMAP
- HBITMAP hBitmap = CreateCompatibleBitmap(hScreenDC, width, height);
- // 将BITMAP选择入内存DC。
- HBITMAP hOldBM = (HBITMAP)SelectObject(hmemDC, hBitmap);
- // BitBlt屏幕DC到内存DC,根据所需截取的获取设置参数
- BitBlt(hmemDC, 0, 0, width, height, hScreenDC, x, y, SRCCOPY);
- // 将旧的BITMAP对象选择回内存DC,返回值为被替换的对象,既所截取的位图
- hBitmap = (HBITMAP)SelectObject(hmemDC, hOldBM);
- // 位图数据大小
- DWORD dwBitmapArraySize;
- // 位图信息头
- BITMAPINFO bmInfo;
- PVOID lpvpxldata;
- // 为位图数据申请内存空间
- dwBitmapArraySize = ((((width*32) + 31) & ~31)>> 3)* height;
- lpvpxldata = HeapAlloc(GetProcessHeap(),HEAP_NO_SERIALIZE,dwBitmapArraySize);
- ZeroMemory(lpvpxldata,dwBitmapArraySize);
- // 添充 BITMAPINFO 结构
- ZeroMemory(&bmInfo,sizeof(BITMAPINFO));
- bmInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- bmInfo.bmiHeader.biWidth = width;
- bmInfo.bmiHeader.biHeight = height;
- bmInfo.bmiHeader.biPlanes = 1;
- bmInfo.bmiHeader.biBitCount = 32;
- bmInfo.bmiHeader.biCompression = BI_RGB;
- GetDIBits(hmemDC, hBitmap, 0, bmInfo.bmiHeader.biHeight,lpvpxldata, &bmInfo, DIB_RGB_COLORS);
- uint8_t* t=(uint8_t*)lpvpxldata;
- for(int i=0;i<height;i++){
- for(int j=0;j<width;j++){
- ba[4*(i*width+j)+0]=t[4*((height-1-i)*width+j)+3];
- ba[4*(i*width+j)+1]=t[4*((height-1-i)*width+j)+2];
- ba[4*(i*width+j)+2]=t[4*((height-1-i)*width+j)+1];
- ba[4*(i*width+j)+3]=t[4*((height-1-i)*width+j)+0];
- }
- }
- HeapFree(GetProcessHeap(),HEAP_NO_SERIALIZE,lpvpxldata);
- DeleteDC(hScreenDC);
- DeleteDC(hmemDC);
- }
复制代码 #这里建议大家不要用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文件~
新建一个文本文档:
- <extension xmlns="http://ns.adobe.com/air/extension/3.7">
- <id>com.si2.display.ScreenCapture</id>
- <versionNumber>0.0.1</versionNumber>
- <platforms>
- <platform name="Windows-x86">
- <applicationDeployment>
- <nativeLibrary>ScreenCapture.dll</nativeLibrary>
- <initializer>MyExtensionInitalizer</initializer>
- </applicationDeployment>
- </platform>
- </platforms>
- </extension>
复制代码 保存为ext.xml,注意上面的3.7要跟AIR的版本号一致~
-----------------------------------------我是分割线--------------------------------------------------
接下来,拿出我们的证书(没有的话自行百度之),myPercept.p12,跟之前的文件放到一起,现在我们攒齐了所有的文件了:
-----------------------------------------我是分割线--------------------------------------------------
再然后,就是使用adt来打包ane了:
这里有两个方法,第一个是把AIRSDK下面的adt.bat复制到这个文件夹里面来,但是如果我们要打包很多ane的话就很麻烦,所以第二个方法是把AIRSDK的bin目录设置为系统的环境变量(不会设置可以百度)
进入命令行,来到本目录,输入以下代码:
- 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打开代码行,输入:
- import com.si2.ScreenCapture;
- import flash.display.Bitmap;
- addChild(new Bitmap(new ScreenCapture().captureScreen()));
复制代码 接下来,就是见证奇迹的时刻了~
按下Ctrl+ENTER
是不是能看到你的屏幕显示在舞台上啦~
大家有问题可以问哦= =欢迎交流学习~
整个工程:C+AS放在这里了,需要的下:
2013.7.25更新:
上面那个成品ane今天在Adobe Flash CC里不知为何用不了了。。再上传一份CC里能用的成品~
本文来自:
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
|