控件间hook钩子调用
需求:
由于各种外部通信异步事件都在appbase控件中,因此需要和通信打交道的控件都有通信事件回调的需求,比如:
- urljpg控件中,通过url下载jpg图片并显示到屏幕上,在此控件中需要获取app.onWIFI32事件中bin数据下载完成的消息
- 在扩展板专用驱动控件中,需要获取RTU数据接收完成的消息
因此我们设计了hook钩子调用的方法,所谓钩子,就是在发起者控件中(比如urljpg)发起钩子,而在appbase中对应的事件中,响应钩子并保存执行参数,最后在消息主循环中执行发起控件的消息处理函数(方法或事件)
比如:
第一步:挂钩子
将回调函数urljpg.doWIFI挂到app.onWIFI32事件中:
urljpg控件代码:
void create()
{ //添加钩子,钩在app.onWIFI32事件上,并回调urljpg,doWIFI()事件,该事件有一个整数类型的参数
hook_add("onWIFI32","urljpg","doWIFI");
//...... 其他create的代码
}
第二步:appbase消息事件中执行已经钩上的代码
appbase控件中:
void onWIFI32(int m)
{
//执行钩上的事件,
//参数一的onWIFI32必须和当前事件名一致,
//参数二和参数三对应回调的事件,本例中为urljpg.doWIFI
//onWIFI32
if (m==4){ //httpdnbin 下载二进制数据完成
hook_run("onWIFI32","*","*"); //获取onWIFI32所有的hook项目,并可赋值
hook_set(wifi_getinfo(5)); //url
hook_set(wifi_getinfo(19)); //size
}
}
注意:
- 由于回调函数是放在主消息循环中调用的,因此wifi_getinfo将不能在回调函数中获取正确的值,因此需要将需要用的参数使用hoot_set函数存入hook参数区,并在回调函数中使用hook_get函数获取值。
- hook参数区目前设置最大值为6个
- 如果是页面中有继承app.onWIFI32,别忘了在页面代码中使用super.onWIFI32调用appbase中原始onWIFI32事件,否则容易遗漏hookrun
//页面代码中
void app.onWIFI32(int m){
...... //原有处理
super.onWIFI32(m); //如果不加,就不会运行原有事件中的hook_run函数
}
第三步:回调函数
urljpg控件代码:
void doWIFI() //处理bin下载完成之后的事件
{
//wifi_httpdnbin
str jurl;
jurl=hook_get(0); //url
//获取URL,如果有多个不同的下载,可以通过URL来识别
if (jurl==url){ //如果是a.jpg,则显示
int size;
size=hook_get(1); //获取下载的a.jpg的实际尺寸
jpg_decode(0xa0000,size,picn); //解码JPG到0号位置,该位置对应图片2048号
st=1; //下载完成
}
}
备注:
- 回调事件必须无参数,否则会调用出错
- 回调事件中需要使用hook_get函数获取暂存的变量值
- 回调函数的调用不是在执行hool_run的时候