MTK的控件和窗体绘制机制及其事件响应机制(一)
一、entryfunction 在文档里面我们看到下面的条款: 以下引自:write applications using pixtel MMI platform.pdf Before display the new screen over previous screen the following must be executed: 1. save the contents of previous screen. 保存前面那个窗体的内容; 2. get the buffer to store the contents of screen to displayed. 获得足够的缓存空间来保存当前要显示的窗体的内容。 3. get display attribute for the following screen, i.e. item to display as lists, circular menu etc. 获得下一个要显示的窗体的属性; 4. retrieve number of submenu items to be displayed. 获取要显示的子菜单条目的个数; 5. set the parent of new screen to be displayed. 设置要被显示的新窗体的父窗体; 6. set the submenu item to be displayed highlighted, on next screen. 设置下一级子菜单要被高亮显示的条目; 7. set the function to be executed on pressing right or left soft key. 设置按下左右软件的执行函数; 8. set the function to be called on exiting the next screen. 设置退出下个窗体的的调用函数; 这些工作一般都在窗体的入口函数里面实现的内容,因此我们有必要先从窗体的入口函数开始。以一段代码来说明(这里省略了很多的东西): void EntryScrIncomingOptions(void) { 1、退出上一窗口,进入新的窗口 EntryNewScreen(ITEM_SCR_INCOMING_OPTIONS,NULL, EntryScrIncomingOptions, NULL); 2、获取当前窗口的GUI buffer guiBuffer = GetCurrGuiBuffer(ITEM_SCR_INCOMING_OPTIONS); 3、获取列表窗口的子菜单数目; number_of_items = GetNumOfChild_Ext(MITEM_OPT_PSEUDO); 4、获取要显示的字符串序列; GetSequenceStringIds_Ext(MITEM_OPT_PSEUDO, list_of_items); 5、设置当前窗口的父窗口的ID; SetParentHandler(MITEM_OPT_PSEUDO); 6、注册highlight 函数 RegisterHighlightHandler(ExecuteCurrHiliteHandler); 7、在已经获取了以上信息后,绘制当前的窗口; ShowCategory1Screen( STR_SCR1002_CAPTION, 0, STR_GLOBAL_OK, IMG_GLOBAL_OK, STR_GLOBAL_BACK, IMG_GLOBAL_BACK, number_of_items, list_of_items, 0, guiBuffer); 8、后面是注册按键函数; SetRightSoftkeyFunction(GoBackHistory, KEY_EVENT_UP); SetKeyHandler(KbCBackCallIncomingRejected, KEY_END, KEY_EVENT_DOWN); SetKeyHandler(KbCBackCallIncomingAccepted, KEY_SEND, KEY_EVENT_DOWN); SetSideVolumeKeysForCM(); SetKeyHandler(GoBackHistory, KEY_LEFT_ARROW, KEY_EVENT_DOWN); } 这是一个典型的窗口入口函数,窗口的进入都是通过类似的这种 entry××function() 来实现。这时引来另外一个问题,就是关于窗口切换是通过什么来实现的,怎么才能保证这些窗口在切换的过程中保持当时的状态。这就涉及到history 管理。 History 的管理是通过栈来实现的。在文档中,我们读到这样的内容: History concept is implemented as a stack. Whenever a new history node is added to the list, it is added at the beginning and whenever a node is deleted it is deleted form the beginning. 历史这个概念是用栈来实现的。当一个新的历史节点加入到这个列表时,它就被加到栈顶,但这个节点被删除时,它就被从栈顶删除。 一般来说历史的应用步骤是这样的: 1. saving screen contents to history. 保存窗体的数据到历史中去。这个数据的内容将在下面提到。 2. going back N levers in history and redrawing screen at that depth. 返回到N 级历史,并重画当时的窗体。 3. deleting N nodes from top of stack from history. 从历史的栈顶删除N个节点。 还是这样一个函数: void EntryFunc() { EntryNewScreen( Screen_ID , Exit_Func , Entry_Func , NULL ); guiBuffer = GetCurrGuiBuffer( SCR_ID_WORDMAIN_LIST ); ShowCategroyXXScreen( Title_ID , … , guiBuffer); } 这里无论是EntryNewScreen的调用,还是guiBuffer的传入,我们都很少考虑过对这些指针和函数在GUI的管理起到了什么样的作用。下面我们就要了解,以上的代码与History管理之间存在的关系。 在MTK环境中,每当我们进入一个窗口,系统将先提取前一个窗口需保留的数据。这些数据包括: 1. 窗口ID ; 2. 进入窗口时调用的函数和退出调用的函数 -- Exit_Func 和 Entry_Func ; 3. 组成窗体的控件的属性(如,列表控件当前高亮显示的条目、当前屏的首末条目等)。 通过跟踪调试程序可以看到 这些动作是在每次调用 EntryNewScreen函数的时候实现的。具体的实现过程就是 :EntryNewScreen函数先将上次执行EntryNewScreen时所记录的currExitScrnID, currEntryFuncPtr以history结构为载体记录入栈;然后执行了记录中的currExitFuncPtr;最后将本窗口的scrnID、exitFuncPtr、entryFuncPtr分别记录入全局变量currExitScrnID、currExitFuncPtr和currEntryFuncPtr,留待下次调用EntryNewScreen时使用。在退出本窗口的时候通过GoBackHistory 出栈,返回到本窗口的父窗口。 举例说明这些数据在实际中是如何被使用的。 假设存在AB两个窗口,A窗口需要保留的数据为data_A。我们先从A窗口进入到B窗口。data_A将在B窗口调用EntryNewScreen()的时候,被压入一个结构类似于栈的数据存储区域;当从B调用GoBackHistory()返回A时,data_A从栈顶被弹出,然后A利用data_A将自身还原到其进入B之前的状态。 这就是History管理的作用。简言之,就是要保持窗口的外观状态。到这里,我们就回答了前面所提出的问题。 |