Authorware的内部消息接口
首先的问题是:我们作的UCD常常在运行期需要创建对象,尤其是对于象dephi这样的开发语言来说,它从运行到消灭的过程中完完全全是依靠创建对象来实现的。在dephi程序中,我们无需担心创建的对象会因为无法及时消灭而出现非法操作,除非是在运行期动态创建的对象。当我们关闭一个程序时,dephi会自动从内存中释放该对象所占内存空间,不会导致该内寸会造成永久性丢失。但是如果把对象编译进dll程序中,对象就一定是动态创建的,必须在程序退出前释放该对象,否则会出现非法操作的标示。某个有名的UCD中的MP3播放函数就存在这样的问题:必须要求用户执行释放对象的函数才能正常退出,如果用户是使用windows窗口的系统菜单退出的话,则非法操作不可避免,从另一方面来说,一个好的软件是应该充分考虑到用户操作过程中可能出现的种种问题,我们只能给他们提供方便而不是给他们添加麻烦,对于一个商业化的软件这是基本原则。现在的问题是:我们如何知道用户什么时候关闭程序,也就是需要抓住释放对象的机会。
当然,制作一个系统钩子函数能够解决这个问题。然而,authorware同样给了程序员一个机会,这就是authorware中的对象消息。要使我们的对象能够接收authorware的内部消息,我们第一步就需要把我们的对象加入到authorware的显示对象列表中去。Authorware的显示对象列表是个抽象的概念,它向每个登记到列表中的对象发布消息,我们就可以根据具体的消息来处理。加入对象到显示列表的命令是通过windows api 函数sendmessage来实现的,函数描述如下:
id = SendMessage(pwHandle, APWC_POST, 0, lpPostPB)
参数 描述
pwHandle Authorware 窗口句柄
lpPostPB 指向一个 APWC_POSTPB 参数块的远指针
APWC_POST 这条消息就是告诉authorware我要加入一个对象。(其值为常数:$6000)
返回值
>0: 返回该对象的唯一标示号.
0: 无法加载对象过程.
-1 在dll中的对象过程未找到.
-2 :非法内存.
-3 :参数错误.
lpPostPB 变量结构描述如下:
type
APWC_POSTPB = record
size: Word; //该结构的长度
dll_ptr: PChar; //加载的dll文件名称
function_ptr: PChar; //对象过程函数名称
rect: TRECT; //对象接收消息的区域
port: Integer; //接收消息方式
data_ptr: longint; //对象携带私有数据结构指针
data_size: Word; //对象携带私有数据长度
name_ptr: PChar; //对象变量名
end {APWC_POSTPB};
FAR = APWC_POSTPB;
APWC_POSTPB_PTR = ^APWC_POSTPB;
说明:其中如果没有私有数据,data_ptr 和 data_size可设为零
对象过程函数名必须是用exports导出的函数
port 可取以下三个常量之一:
STATIC_PORT = 0;//适用于基本固定的对象,大多数情况下选它
MOTION_PORT = 1;//适用于更新频率较快的对象
SCREEN_PORT = 2;//适用于直接画屏的对象,如果对象是动画之类就选它
RECT 是一个在authorware的窗口内定义的区域,如果你需要接收象鼠标消息这样
的消息,则只在该区域你才能接收
二 创建对象过程函数
在登记对象之后,authorware就向我门定义的对象过程发送消息,我们根据具体的消息,就实现了控制我们对象。
对象过程函数格式:
opjiectProc(awparam: APWN_AB;msg: NOTIFICATION_MESSAGE):Boolean;
参数说明:
awparam:在我们创建对象过程中定义的指向APWN_AB结构的指针
APWN_AB结构声明如下:
type
APWN_AB = record
size: Word; //该结构的长度
id: LongInt; //分配给对象的唯一标示号
icon_id: Integer; //创建该对象所在图标,通常是使用计算图标//的地方
display: HWND; //authorware主窗口句柄
wparam: WPARAM; //msg的第一参数
lparam: LPARAM; //msg的第二参数
rect: TRECT; //由APWC_POSTPB参数传递过来
data_ptr: longint; //由APWC_POSTPB参数传递过来
data_size: Word; //由APWC_POSTPB参数传递过来
name_ptr: PChar; //由APWC_POSTPB参数传递过来
end {APWN_AB};
FAR = APWN_AB; //声明作为远指针调用(其实在现在32位操作//系统下已无必要 ,可删去)
APWN_AB_PTR = ^APWN_AB;//定义指针
msg:NOTIFICATION_MESSAGE是authorware定义的消息类型
该变量声明如下:
type
NOTIFICATION_MESSAG=WORD;
Msg参数就是authorware传来的消息,它固定为以下几种类型:
消息名称 参数 意义 值
APWN_INIT 对象正在创建. 0
wparam 0
lparam 0
APWN_DESTROY 对象正在消灭并释放所占内存 1
wparam 0
lparam 0
APWN_PAINT 对象在设备描述表上重绘自身 2
wparam HDC (authorware主窗口设备描述表)
lparam 0
APWN_SAVE 对象保存自身的数据以便重载 3
wparam 0
lparam 0
APWN_RESTORE 对象重载保存的私有数据 4
wparam 0
lparam 0
APWN_LBDOWN 鼠标左键按下. 5
wparam 0
lparam (低位字节存放x坐标,高位字节存放y坐标)
APWN_LBDBLCK 鼠标左键双击. 6
wparam 0
lparam (低位字节存放x坐标,高位字节存放y坐标)
APWN_LBUP 鼠标左键抬起. 7
wparam 0
lparam (低位字节存放x坐标,高位字节存放y坐标)
APWN_WINDOWOPEN 8
wparam 0
lparam 0
APWN_WINDOWCLOSE authorware主窗口打开/关闭 9
wparam 0
lparam 0
APWN_SETPROPERTY 系统使用了SetProperty()函数 10.
wparam 0
lparam APWN_PROP_PTR(这是另一个authorware定义的结构参数)
APWN_GETPROPERTY 获取对象值. 11
wparam 0 (not used)
lparam APWN_PROP_PTR
APWN_CLOSEWINDOW 当系统函数CloseWindow()被调用时就会传递该消息 12
wparam 0
lparam 0
APWN_MOUSEMOVE 鼠标在对象上移动. 13
wparam 0
lparam (低位字节存放x坐标,高位字节存放y坐标)
APWN_HITTEST 鼠标停留在对象边界. 14
wparam 0
lparam (低位字节存放x坐标,高位字节存放y坐标)
APWN_USER 自定义消息 10000
这里关键的消息就是 APWN_WINDOWCLOSE,这个消息告诉我们authorware程序即将关闭,我们可相应这条消息来释放我们的对象。现在我们就用一个实例来阐述如何捉住这条消息。
打开我们前面做的函数X_createmediacontrol源代码档,在uses 语句后添加如下声明:
……
/////////////////
type
APWC_POSTPB = record
size: Word;
dll_ptr: PChar;
function_ptr: PChar;
rect: TRECT;
port: Integer;
data_ptr: longint;
data_size: Word;
name_ptr: PChar;
end {APWC_POSTPB};
FAR = APWC_POSTPB;
APWC_POSTPB_PTR = ^APWC_POSTPB;
///////////////////////
type
APWN_AB = record
size: Word;
id: LongInt;
icon_id: Integer;
display: HWND;
wparam: WPARAM;
lparam: LPARAM;
rect: TRECT;
data_ptr: longint;
data_size: Word;
name_ptr: PChar;
end {APWN_AB};
APWN_AB_PTR = ^APWN_AB;
/////////////////////////////
type
APW_NOTIFICATION_MESSAGE = Word;
const APWN_INIT = 0;
const APWN_DESTROY = 1;
const APWN_PAINT = 2;
const APWN_SAVE = 3;
const APWN_RESTORE = 4;
const APWN_LBDOWN = 5;
const APWN_LBDBLCK = 6
const APWN_LBUP= 7
const APWN_WINDOWOPEN=8
const APWN_WINDOWCLOSE = 9
const APWN_SETPROPERTY =10
const APWN_GETPROPERTY =11
const APWN_HITTEST 11
const APWN_CLOSEWINDOW= 12.
const APWN_MOUSEMOVE = 13;
const APWN_HITTEST = 14;
const STATIC_PORT = 0;
const MOTION_PORT = 1;
const SCREEN_PORT = 2;
const APWC_POST = $6000;
……
找到 function createmediacontrol(awparam:AWPARAM_PTR;visible,x,y:integer;filename:Pchar):longint;stdcall;//注 //意此处返回值类型改为longint,同时声明部分也要相应修改
//添加
var
postpb:APWC_POSTPB_PTR;
wpostpb:longint;
szfilename:Pchar;
begin
…… //创建过程不变
//在result=。。。之前添加如下代码:
getmem(szfilename,255);//给dll文件名分配内存
GetModuleFileName(hinstance,szfilename,255);//取得文件名
postpb.size:=sizeof(postpb);//设置APWC_POSTPB_PTR参数长度
postpb.dll_ptr:=szfilename;//设置APWC_POSTPB_PTR 文件名
postpb.function_ptr:='newproc';//定义对象过程函数
setrect(postpb.rect,0,0,200,200);//定义区域,无所谓,可大可小
postpb.port:= STATIC_PORT; //定义消息接收模式
postpb.name_ptr:='myproc';//定义APWC_POSTPB_PTR变量名,随便给一个好了
postpb.data_ptr:=0; //定义APWC_POSTPB_PTR 携带私有数据
postpb.data_size:=0;// 定义APWC_POSTPB_PTR 携带私有数据长度
wpostpb:=longint(postpb); //定义APWC_POSTPB_PTR的指针
sendmessage(awparam.hwnd, APWC_POST,0,wpostpb);//向authorware发送消息
……
接下来,就该写对象函数过程了,前面定义的函数名为newproc
则函数名需要保持一致
function newproc(APWNPTR:APWN_AB_PTR ;msg:word):longint;stdcall;
begin
if msg=APWN_WINDOWCLOSE then //假如消息为窗口即将关闭,即用户按下了关闭按钮或使用了退出//函数
mediaplayer.free;
result:=1;
end;
……
最后在exports中导出newproc函数
……
exports
……
newproc,
……
这样当开发者使用创建函数创建了媒体播放器后,无需关心用户何时候退出,因为系统在接收到程序关闭消息会将该消息传递给newproc函数过程,从而就可以及时释放该媒体播放器这个对象了。