《2022年深入BREW消息处理机 .pdf》由会员分享,可在线阅读,更多相关《2022年深入BREW消息处理机 .pdf(3页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、深入 BREW 消息处理机制作者:东方欲晓消息处理机制, 即 event driven和传统的编程机制不同,如 dos ,unix 下的 c 编程,他没有 main loop,程序的流程不是顺序执行的。有过window编程经历的读者都会清楚这种机制。Windows下消息处理机制:当在交互中进行一个action (or signal, or input, etc ) ,window产生相应的 event ,通过 window的 event dispatch机制, 相应的窗口或者app 得到该 event ,从而触发相应的 event handler fun进行处理。BREW 下消息处理机制简而言
2、之也相似,即 BREW 环境(这里是 AEE Shell)捕捉到 event后,dispatch到相应的 app 或者 control,由其 event handler fun处理。区别:我们知道BREW的体系结构采用了COM方式,即具有面向对象的类层次结构,从而其具体的event handler fun也是作为各个Interface的外露的接口函数的形式被运用。一个applet本质上来说就是一个实例化的IAPPLET类, 所以这样就统一了所有在applet中运用的 event handler fun都是各个Interface的外露接口函数的说法。具体而言,这些event handler fu
3、n还是有区别的,主要是IAPPLET_Handleevent和其他 Interface的 Handleevent的区别。IAPPLET_Handleevent是通过在AEEClsCreateInstance中的 AEEApplet_New函数被注册实例化的, AEEApplet_New函数实例化用户的APPLET 的 Class同时也通过传入USERAPP_HandleEvent参数实例化了IAPPLET_Handleevent。除了 IAPPLET 具有 handleevent外,所有的继承Icontrol接口的 Interface也具有事件处理函数,允许 处 理事 件 。 这 些 各 种
4、具 体 的 Icontrol_handleevent有两种方 式被 调 用 。 一种 是 在applet的handleevent中由 programmer显式的调用,如:switch (eCode) case EVT_APP_START: return(TRUE); case EVT_APP_STOP: . Case EVT_KEY: IMENU_Handleevent.ItextCtl_Handleevent.另一种是当这些Control包含于 Dialog中,且处于focus状态时,这些事件处理函数的触发是隐式的,是由 AEE 机制自动触发的,无需在代码中显式的调用这些handleeven
5、t。Idialog接口没有外露的handleevent接口函数,但是允许通过Idialog_seteventhandle来注册一个该Dialog的事件处理函数。 需要注意的是, 该事件处理函数是何时被触发的:一旦当一个dialog处于 active时, aee shell将会把所有的event直接发往该dialog ,该 dialog会自动的调用处于focus的 control的 handleevent来处理该事件,只有当该control没有处理该事件时,dialog注册的事件处理函数才会被调用。Brew 中的 handle event函数都是 boolean返回类型的,这是为了实现事件处理的
6、层次机制,当该层上的 handle event没有处理该事件时,应该返回false ,以便上层对该事件感兴趣的handle event来处理。 如果处理了,应该返回TRUE ,说明该事件已被处理,无需其他层再处理。有了以上知识后,下面给出完整的BREW 环境下消息分发和处理的流程。首先 BREW 存在于一个task 中,尽管允许 brew运行于一个单独的task 中,但是实际oem中都是将其运行于现有的一个task中,比如 ui task。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - -
7、第 1 页,共 3 页 - - - - - - - - - 当 brew运行后,首先 ui task中捕捉到各种事件, 此时 ui task通过 aee_dispatch将事件分发至brew环境中,brew环境再通过aee_sentevent具体分发事件至目的地。接着在两种不同的情况下将走不同的流程。如果当前没有active dialog,则紧接着IAPPLET_Handleevent被 brew自动调用来处理事件,而此时调用的 IAPPLET_Handleevent其实就是用户注册的自己的applet_handleevent。从而实现了允许用户 app 捕捉到事件并处理的机制。在用户的app
8、 handleevent中,用户可以将事件继续下发,比如通过调用 IMENU_handleevent等将事件下发给各种控件处理。如果当前有active dialog,则紧接着Adialog_event被 brew自动调用,从而使得事件被dialog最先截获,而 dialog之后的处理是检查包含的控件中哪个处于focus ,并将事件下发给它的handleevent来处理,同时根据其返回值来判断其是否已经处理了该事件,当其返回False 后, dialog将该事件继续转发至该 dialog注册的 handleevent(如果有的话) ,如果该 handleevent仍然返回 false ,brew
9、继续将该事件转发至 app handleevent。 这种机制使得当以dialog方式来创建应用时, 各种 event被自动的处理,从而简化了代码量,但也使得事件流程更加晦涩,用户的程序不能直接的控制它。最后,结合一个我工作中的问题,来加深对brew事件处理机制的理解。这是一个关于输入法的问题,当在textctl中进行输入时,如果是拼音和笔画输入时,情况比较复杂,大致如下:app handleevent调用 itextctl_handleevent来处理按键事件, itextctl_handleevent的 oem实现中最后会创建一个拼音dialog ( pinyindlg)用来显示输入的拼音
10、和候选字,同时注册一个dialoghandler( pinyindlgevent) , pinyindlg中 包 含 一 个 control( ipinyinmanager) , 它 的handleevent(ipinyinmanager_handleevent)主要来处理用户拼音输入时如何显示候选字等等一系列的复杂任务。这样的话,当处于拼音输入模式时,输入第一个字母后,就创建了pinyindlg来显示候选字,同时ipinyinmanager_handleevent被激活,之后按的任何键都会直接调用该ipinyinmanager_handleevent来处理,且该handleevent均返回
11、true ,表示正确处理了。如此,则所有按键事件将均被ipinyinmanager_handleevent截获, app ,以及 itextctl均没有机会处理事件。那如何退回到text控制之下那?以便进行其他操作,比如删除,切换,保存等。这是通过在ipinyinmanager_handleevent中对特殊的键进行特殊处理来实现的,比如定义clr 为退回至 text控制,则在 ipinyinmanager_handleevent中当 key 为 avk_CLR时,return false,从而使得pinyindlg注册的 pinyindlgevent有机会被调用,而在这个handleeven
12、t中 release pinyindlg,并且返回 true 。这样就release了 dlg ,从而使得下次的按键可被app捕获,由app handleevent 传给itextctl_handleevent,从而成功的使得event处理的焦点回到了itextctl。这里 return true是为了避免同时删除最后一个汉字(false使得 itextctl_handleevent再次处理该clr ,就会删除一个汉字) 。我们知道,应用可以设置maxchars来限制 text中输入的最大字符数。当输入为字母,数字,符号时没有问题。但是当输入为拼音时,当达到最大输入数时会出现一种情况,就是不能
13、输入进text了,但是拼音dlg 继续存在,且随着不断的按键继续有不断的响应(比如候选字不断变化等)。这是由于oem层当输入达到最大值时的处理是,仅仅不往text buffer中存入字符而并没有实现:release掉 pinyindlg,回到text 控制下,不响应用户任何输入这些功能。如何解决这个问题那?当对brew事件处理机制很熟悉的话,问题就迎刃而解了。只需要当输入达最大数时的同时将event处理控制权释放即可,这样下次事件处理将重新由app 捕获,并传给itextctl,而在itextctl的 handleevent的 oem 实现中进行判断,当已达最大输入时,不作任何响应。具体如下:
14、ipinyinmanager_handleevent中有对 select事件进行处理,主要就是add char到 text中,我们在add char这个处理之后,加入对最大输入数是否已到的判断,如果最大数已到,则直接return false 释放 event handle的控制权。之后,pinyindlg注册的 pinyindlgevent会继续处理这个事件(即select键) ,在这个 eventhandle中 release掉 pinyindlg,使其不再显示,同时返回true (这是为了让该事件select不 再 传 至app , 否 则app可 能 采 取 保 存 等 操 作 )。 这
15、 样 下 次 按 键 将 顺 利 被 传 至名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 2 页,共 3 页 - - - - - - - - - itextctl_handleevent,在该 handleevent的 oem 实现中, 我们加入对输入最大数的判断,如果已达最大数,则不作任何响应,同时返回true (对程序而已,的确是作出了响应:) ) 。 这样就达到了当拼音输入达最大数的同时自动隐去拼音框,之后再按任何键无响应的合理效果。以上是我一段时间工作后的心得体会,可能有不当之处,大家相互交流。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 3 页,共 3 页 - - - - - - - - -