MTK窗口绘制机制

关于窗体(category screen)

mtk的控件和窗体绘制机制以及控件、窗体的事件响应机制

一、

entryfunction

在文档里面我们看到下面的条款:

Before display the new screen over previous screen the following must be executed: 1. 2. 3. 4. 5. 6. 7. 8.

save the contents of previous screen. 保存前面那个窗体的内容;

get the buffer to store the contents of screen to displayed. 获得足够的缓存空间来保存当前要显示的窗体的内容。

get display attribute for the following screen, i.e. item to display as lists, circular menu etc. 获得下一个要显示的窗体的属性;

retrieve number of submenu items to be displayed. 获取要显示的子菜单条目的个数; set the parent of new screen to be displayed. 设置要被显示的新窗体的父窗体;

set the submenu item to be displayed highlighted, on next screen. 设置下一级子菜单要被高亮显示的条目;

set the function to be executed on pressing right or left soft key. 设置按下左右软件的执行函数;

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(

以下引自:write applications using pixtel MMI platform.pdf

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管理的作用。简言之,就是要保持窗口的外观状态。到这里,我们就回答了前面所提出的问题。

二、

窗口的绘制

绘制窗体实际上可以看作是绘制轮廓和绘制组件两个部分。 我们先看这么一个文件 CustCoordinates.c

这个文件主要是定义了这么一个宏 g_categories_controls_map:

或者类似于这样的定义,这个数组就具体的将窗体的轮廓以及窗体的各个组件的位置作出了定义 下面我们以一个具体的例子作为说明: const U8 category5[] = {

5, // 这个代表组件的个数; DM_BASE_LAYER_START, DM_SCR_BG,

DM_BASE_CONTROL_SET1,

// 开始层; // 背景;

//表示窗体的基本组成——状态栏、标题和软按键 //多行输入框

DM_MULTILINE_INPUTBOX1, };

DM_CATEGORY_CONTROLLED_AREA // 输入法的部分; 这些组件被定义在枚举结构mmi_dm_control_ids_enum中。

const S16 coordinate_set5[] = {

DM_FULL_SCREEN_COORDINATE_FLAG,

联系客服:779662525#qq.com(#替换为@) 苏ICP备20003344号-4