收藏 分销(赏)

人力资源-mmi培训资料--自定义模板.docx

上传人:pc****0 文档编号:8499647 上传时间:2025-02-15 格式:DOCX 页数:16 大小:19.66KB
下载 相关 举报
人力资源-mmi培训资料--自定义模板.docx_第1页
第1页 / 共16页
人力资源-mmi培训资料--自定义模板.docx_第2页
第2页 / 共16页
点击查看更多>>
资源描述
mtk平台mmi培训资料(中文) 2008-06-06 21:48 本文详细说明了如何建设一个自定义列表窗体模板。原理部分请参见《MTK平台(1)——如何添加一个窗体模板》。 最终实现的是一个字典输入界面。布局为:该模板不包含业务逻辑,仅提供页面显示和InputBox框输入事件后的ListBox的Redraw事件的注册,以及基本的输入法设置、清空后的返回函数。 一、添加用户自定义列表模板的过程 (一)在g_categories_controls_map[]中加入: ,{MMI_CATEGORY_CUSTOM_LIST,(U8*)custom_define_list,(s16*)coordinate_custom_list,NULL} const U8 custom_define_list[]= {     5,      DM_BASE_LAYER_START,     DM_SCR_BG,     DM_BASE_CONTROL_SET1,     DM_SINGLELINE_INPUTBOX1,     DM_LIST1 }; const S16 coordinate_custom_list[]= {     DM_FULL_SCREEN_COORDINATE_FLAG,     DM_CUSTOM_DEFINE_INPUTBOX,     //需要定义     DM_CUSTOM_DEFINE_LIST      //需要定义 }; (二)在dm_get_coordinates()函数中加入: //设定列表位置和大小(不要忘记全局变量 MMI_custom_Listbox_x 等的定义) else if( *UICtrlAccessPtr_p == DM_CUSTOM_DEFINE_LIST ) {    dm_coordinate_info->s16X = MMI_custom_Listbox_x;       dm_coordinate_info->s16Y = MMI_custom_Listbox_y;      dm_coordinate_info->s16Width = MMI_custom_Listbox_width;   dm_coordinate_info->s16Height = MMI_custom_Listbox_height;       dm_coordinate_info->Flags = DM_NO_FLAGS; UICtrlAccessPtr_p ++ ; } //设定输入框位置和大小 else if( *UICtrlAccessPtr_p == DM_CUSTOM_DEFINE_INPUTBOX ) {    dm_coordinate_info->s16X = MMI_custom_inputbox_x ;        dm_coordinate_info->s16Y = MMI_custom_inputbox_y;        dm_coordinate_info->s16Width = MMI_custom_inputbox_width ;   dm_coordinate_info->s16Height = MMI_custom_inputbox_height;    dm_coordinate_info->Flags = DM_SINGLE_LINE_INPUTBOX_SPECIFIC_HEIGHT;    UICtrlAccessPtr_p ++ ; } (三)在Wgui_category.c中定义模板显示函数 void ShowCategoryCustomListScreen(         U8 *title,         U16 title_icon,         U16 left_softkey,         U16 left_softkey_icon,         U16 right_softkey,         U16 right_softkey_icon,         S32 number_of_items,         U8 **list_of_items,         U16 *list_of_icons,         S32 flags,         S32 highlighted_item,         U8 *history_buffer) {     /*----------------------------------------------------------------*/     /* Local Variables                                                */     /*----------------------------------------------------------------*/     dm_data_struct dm_data;     S32 i;     U8 h_flag;     /*----------------------------------------------------------------*/     /* Code Body                                                      */     /*----------------------------------------------------------------*/     gdi_layer_lock_frame_buffer();     SetupCategoryKeyHandlers();     MMI_title_string = (UI_string_type) title;     MMI_title_icon = (PU8) get_image(title_icon);    change_left_softkey(left_softkey, left_softkey_icon);     change_right_softkey(right_softkey, right_softkey_icon); //Create List      create_fixed_icontext_menuitems();     associate_fixed_icontext_list();     ShowListCategoryScreen(         (UI_string_type) title,         get_image(title_icon),         get_string(left_softkey),         get_image(left_softkey_icon),         get_string(right_softkey),         get_image(right_softkey_icon),         number_of_items);     for (i = 0; i < number_of_items; i++)     {         add_fixed_icontext_item((UI_string_type) list_of_items[i], wgui_get_list_menu_icon(i, list_of_icons[i]));          }     h_flag = set_list_menu_category_history(MMI_CATEGORY_CUSTOM_LIST, history_buffer);     if (h_flag)     {         fixed_list_goto_item_no_redraw(MMI_fixed_list_menu.highlighted_item);     }     else     {         fixed_list_goto_item_no_redraw(highlighted_item);     } //Create Inputbox     memset(custom_single_input_buffer,0,100);     pfnUnicodeStrcpy(custom_single_input_buffer,L"Custom Category");     wgui_setup_singleline_inputbox(         0,         0,         240,         320,         custom_single_input_buffer,         pfnUnicodeStrlen(custom_single_input_buffer),         MMI_CATEGORY_CUSTOM_LIST,         get_string(right_softkey),         get_image(right_softkey_icon),         INPUT_TYPE_ALPHANUMERIC_LOWERCASE| INPUT_TYPE_USE_ONLY_ENGLISH_MODES,         history_buffer,         0);     register_hide_multitap(wgui_hide_multitap);     gdi_layer_unlock_frame_buffer();     ExitCategoryFunction = ExitCategoryCustomListScreen;     dm_setup_category_functions(dm_redraw_category_screen, dm_get_category_history, dm_get_category_history_size);     dm_data.s32ScrId = (S32) GetActiveScreenId();     dm_data.s32CatId = MMI_CATEGORY_CUSTOM_LIST;    //不要忘记该常量MMI_CATEGORY_CUSTOM_LIST的定义     dm_data.s32flags |= DM_CLEAR_SCREEN_BACKGROUND;     //dm_data.s32flags |= DM_SHOW_VKPAD;      dm_register_vkpad_callback(CustomList_virtual_keypad_callback);     dm_setup_data(&dm_data);     dm_redraw_category_screen(); }   /* end of ShowCategory353Screen */ void CustomList_virtual_keypad_callback(void) { #if defined(__MMI_TOUCH_SCREEN__)     mmi_pen_editor_clear_and_show_virtual_keyboard_area(); #endif    gui_show_transparent_image(0,200,GetImage(IMG_H_SELECT_LEFT),0); } void ExitCategoryCustomListScreen() { wgui_close_singleline_inputbox(); } (四)在singleline_inputbox_multitap_input()函数中添加用户处理key_0~key_9的按键事件的函数: void (*singleline_inputbox_custom_input_callback) (void) = UI_dummy_function; void singleline_inputbox_multitap_input(UI_character_type c) {     /*----------------------------------------------------------------*/     /* Local Variables                                                */     /*----------------------------------------------------------------*/     /*----------------------------------------------------------------*/     /* Code Body                                                      */     /*----------------------------------------------------------------*/     if (MMI_singleline_inputbox.flags & UI_SINGLE_LINE_INPUT_BOX_PLUS_CHARACTER_HANDLING)     {         if ((MMI_singleline_inputbox.text[0] == '+') &&             (MMI_singleline_inputbox.current_text_p == MMI_singleline_inputbox.text) &&             (MMI_singleline_inputbox.text_length >= (MMI_singleline_inputbox.available_length - ENCODING_LENGTH)))         {             return;         }     }     gui_single_line_input_box_insert_multitap_character(&MMI_singleline_inputbox, c);     redraw_singleline_inputbox();     singleline_inputbox_input_callback();     singleline_inputbox_custom_input_callback(); } (五)Wgui_Category.c中添加用户事件定义接口 //右键事件注册 void SetCategoryCustomListRightSoftkeyFunction(void (*f) (void)) {     wgui_singleline_inputbox_RSK_function = f; } //key_0到key_9按下时的事件注册 extern void (*singleline_inputbox_custom_input_callback) (void); void SetCategoryCustomListNumKeyFunction(void (*f) (void)) { singleline_inputbox_custom_input_callback = f ; } //设置InputBox大小 void SetCustomList_Inputbox_Size(S32 p_x , S32 p_y , S32 p_width , S32 p_height ) { MMI_custom_inputbox_x = p_x ; MMI_custom_inputbox_y = p_y ; MMI_custom_inputbox_width = p_width ; MMI_custom_inputbox_height = p_height ; } //设置ListBox大小 void SetCustomList_Listbox_Size(S32 p_x , S32 p_y , S32 p_width , S32 p_height ) { MMI_custom_Listbox_x = p_x ; MMI_custom_Listbox_y = p_y ; MMI_custom_Listbox_width = p_width ; MMI_custom_Listbox_height = p_height ; } 二、自定义列表模板的使用方法 1、 调用SetCustomList_Inputbox_Size 和 SetCustomList_Listbox_Size 设置列表框和输入框的大小。 2、 调用显示窗体的接口 ShowCategoryCustomListScreen。 3、 调用右键事件注册函数,注册文本框被清空后的事件(如返回等)SetCategoryCustomListRightSoftkeyFunction。 4、 调用key_0至key_9的事件注册函数,SetCategoryCustomListNumKeyFunction()。 三、参数详细说明 ① void SetCustomList_Inputbox_Size(S32 p_x , S32 p_y , S32 p_width , S32 p_height ) 与    void SetCustomList_Listbox_Size(S32 p_x , S32 p_y , S32 p_width , S32 p_height ) p_x , p_y :起始位置 p_width , p_height : 大小。 ② void SetCategoryCustomListRightSoftkeyFunction(void (*f) (void))    void SetCategoryCustomListNumKeyFunction(void (*f) (void))    f(void) :函数地址。 ③ void ShowCategoryCustomListScreen(         U8 *title,       // 标题文本指针         U16 title_icon,      // 标题图标ID         U16 left_softkey,     // 左键文本ID         U16 left_softkey_icon,    // 左键图标ID         U16 right_softkey,     // 右键文本ID         U16 right_softkey_icon,    // 右键图标ID         U8* custom_single_input_buffer, // Input输入Buffer         S32 number_of_items,    // 列表条目数         U8 **list_of_items,     // 列表项文本指针数组         U16 *list_of_icons,     // 列表项Icon         S32 highlighted_item,    // 当前高亮显示的列表条目         U8 *history_buffer)     // 历史记录Buffer 附:所需更改的文件 wgui.c wgui_categories.c wgui_draw_manager.c wgui_inputs.c wgui.h wgui_categories_defs.h wgui_draw_manager.h CustCoordinate.c 一、什么是History管理     对于我们上层用户而言,经常接触到的History管理是这样的:     void EntryFunc() { U8 *guiBuffer;      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.    组成窗体的控件的属性(如,列表控件当前高亮显示的条目、当前屏的首末条目等)。 举例说明这些数据在实际中是如何被使用的。 假设存在AB两个窗口,A窗口需要保留的数据为data_A。我们先从A窗口进入到B窗口。data_A将在B窗口调用EntryNewScreen()的时候,被压入一个结构类似于栈的数据存储区域;当从B调用GoBackHistory()返回A时,data_A从栈顶被弹出,然后A利用data_A将自身还原到其进入B之前的状态。 这就是History管理的作用。简言之,就是要保持窗口的外观状态。 二、History管理的机制     现在,我们来了解一下前面所说的data_A的数据结构是什么样的。 typedef struct _history {     U16 scrnID;      //(1)Screen ID (窗口号)     FuncPtr entryFuncPtr;   //(2)EntryNewScreen时要进入的 Entry_Func     U8 inputBuffer[MAX_INPUT_BUFFER];          //(3)没遇到过其使用,都是NULL。     U8 guiBuffer[MAX_GUI_BUFFER];          //(4)窗体中控件的一些需保存的信息的Buffer,通常//在使用时被转化成各控件自定义的结构体如: list_menu_category_history。 } history;          而存放data_A的类似于堆栈的数据区则以全局变量的形式定义在系统中: historyNode historyData[MAX_HISTORY]; (MAX_HISTORY = 50): 设当前窗口A所对应的数据是historyData[ EntryScreenNum – 1 ] ,那么它是何时、是如何被赋值的?又是何时、如何被使用的? 经过跟踪调试,我们已经知道,在由窗口A进入到窗口B(调用EntryNewScreen)的时候,我们将data_A记录到了historyNode 的结构体变量中。但是,在EntryNewScreen的时候传入的,却是data_B,data_A是如何被记录和使用的呢? 我们摘选EntryNewScreen的子函数中所包含的较核心的代码来说明这个问题。这三段代码是按照现在的排放顺序来执行的。 第一段(history h 可理解为data_A):     h.scrnID = scrnID;     // scrnID = currExitScrnID     h.entryFuncPtr = entryFuncPtr; // entryFuncPtr = currEntryFuncPtr     pfnUnicodeStrcpy((S8*) h.inputBuffer, (S8*) & nHistory);                                        // nHistory = NULL ;         GetCategoryHistory(h.guiBuffer);  //GetCategoryHistory是指向获取//guiBuffer的函数的指针     AddHistory(h);      //数据入栈 第二段: if(currExitFuncPtr)     {    //…         (*currExitFuncPtr) ();   //执行Exit_Func     } 第三段(记录Screen_ID,Exit_Func和EntryFunc): currExitScrnID = scrnID;     currExitFuncPtr = exitFuncPtr;     currEntryFuncPtr = entryFuncPtr; 这样,我们就可以看出,EntryNewScreen函数先将上次执行EntryNewScreen时所记录的currExitScrnID, currEntryFuncPtr以history结构为载体记录入栈;然后执行了记录中的currExitFuncPtr;最后将本窗口的scrnID、exitFuncPtr、entryFuncPtr分别记录入全局变量currExitScrnID、currExitFuncPtr和currEntryFuncPtr,留待下次调用EntryNewScreen时使用。 下面有数据出入栈流程,有兴趣的话可以跟踪一下。以先后顺序代表包含关系,如下: 1.入栈(EntryNewScreen): (1)U8 EntryNewScreen(U16 newscrnID, FuncPtr newExitHandler, FuncPtr newEntryHandler, void *peerBuf) (2)static void ExecuteCurrExitHandler(void); (3)void ExecuteCurrExitHandler_Ext(void); (4)void GenericExitScreen( U16 scrnID , FuncPtr entryFuncPtr ); (5)void AddHistoryReference(history *addHistory); //处理historyData (6)S16 increment();         //更改栈指针 2.出栈(GoBackHistory): (1)void GoBackHistory(void); (2)static void ExecutePopHistory(void);        //处理historyData (3)static U8 decrement(void);                       //更改栈指针 现在我们已经知道了history 的三个结构体成员是如何记录的了,最后来重点看一下history.guiBuffer是如何被记录和使用的。 三、GUI Buffer对控件属性的记录     由上2节我们知道,guiBuffer是窗体中某些控件的需保存的属性的Buffer,通常在使用时被转化成各控件自定义的结构体。如: list_menu_category_history。 现在有几个问题需要我们解答: 1.    guiBuffer 指向的Buffer是如何被分配的?该块数据是动态的还是静态的? 2.    这块 Buffer 是何时被写入数据的? 3.    如何释放(动态分配时)或清空(固定地址时)该块 Buffer ? 让我们逐一解答上面的三个问题,以清晰我们对guiBuffer的认识。 1.    答:在void AddHistoryReference(history *addHistory)中,调用OslMalloc(MAX_GUI_BUFFER)动态申请了一块内存,用来保存在 GenericExitScreen 中获取的history.guiBuffer。[参见出入栈流程] 2.    如何释放(动态分配时)或清空(固定地址时)该块 Buffer ? 答 :在static void decrement (void)函数中,该buffer被释放: OslMfree(historyData[currHistoryIndex].guiBuffer);。[参见出入栈流程] 3.    答 : 只要一个窗体模板有需要保存状态的控件,它们都调用了这个函数——dm_setup_category_functions()。函数定义如下: void dm_setup_category_functions(         FuncPtr redraw_function,         U8 *(*get_history_function) (U8 *buffer),         S32(*get_history_size_function) (void) ) { //指向窗体重画函数的函数指针     RedrawCategoryFunction = redraw_function; //指向获取窗体guiBuffer的函数指针     GetCategoryHistory = get_history_function; //指向获取窗体guiBuffer大小的函数指针     GetCategoryHistorySize = get_history_size_function; } 在只有一个控件的状态需要保存的窗体中,会这样传参给这个函数: dm_setup_category_functions(dm_redraw_category_screen, dm_get_category_history, dm_get_category_history_size); GenericExitScreen()函数中,将使用 GetCategoryHistory()获取某个控件的GuiBuffer[参见出入栈流程]。如果按照上面的设置,GetCategoryHistory指向了 dm_get_category_history这个函数。看看这个函数做了什么: control_set_ptr = dm_search_control_set((U16) p_dm_data->s32CatId, &coordinate_set_p); //获取窗体模板内的控件类型数组control_set_ptr u8NoOfUICtrls = control_set_ptr[0]; //获取数组内变量个数,即控件的个数 /*根据控件类型,获取控件的guiBuffer.值得注意的是,1.这里的histroy_Buffer的名称起的不好,应该起名为guiBuffer,不应混淆视听;2.最终history_buffer 将指向模板中定义的最后一个控件的guiBuffer*/    for (u8CtrlCt = 1; u8CtrlCt <= u8NoOfUICtrls; u8CtrlCt++) { switch (control_set_ptr[u8CtrlCt]) {     case DM_CIRCULAR_MENU1:    {        get_circular_menu_category_history((U16) p_dm_data->s32CatId, history_buffer);        break;     }     case DM_LIST1:     {         get_list_menu_category_history((U16) p_dm_data->s32CatId, history_buffer);         break;     }     case DM_DYNAMIC_LIST1:     {          get_list_menu_category_history((U16) p_dm_data->s32CatId, history_buffer);          break;      }      case DM_ASYNCDYNAMIC_LIST1:      {          get_list_menu_category_history((U16) p_dm_data->s32CatId, history_buffer);          break;       }       //... } //... } 而在模版显示函数(ShowCategroyXXScreen)中,则根据 guibuffer 的情况设置控件的属性。如果 guibuffer 不为空,则说明该模板的显示函数是在GoBackHistory()的时候被调用的,而不是进入新窗口时被调用的。那么控件必然有一些保留的属性需要被还原。以6号窗口的List为例。在ShowCategory6Screen()中,调用下面的函数来恢复List设置: h_flag = set_list_menu_category_history(MMI_CATEGORY6_ID, history_buffer); 这样guiBuffer的Get和Set就统一起来了。 现在,我们已经知道了guiBuffer 所起到的作用。但是,如果一个窗体模板内有两个或两个以上需要记录状态的控件,又该怎么办呢? ps:该死的字数限制,只能把剩下的放到《MTK平台(3)——History管理[下]》了。 四、灵活使用guiBuffer 在我们自己设计窗体模板时,经常会出现一个窗体中有多个控件的情况。但是,如果一个窗体中有两个控件、却依然调用dm_get_category_history()获取控件的GuiBuffer的话,就会出现问题。比如,我们在制作CustomList窗体时,初期使用了这样的代码: (1)模板中的组件设置: const U8 custom_define_list[]= {      5,      DM_BASE_LAYER_START,      DM_SCR_BG,      DM_BASE_CONTROL_SET1,      DM_SINGLELINE_INPUTBOX1,   //单行输入控件      DM_LIST1        //列表控件 };     (2)窗体显示函数 ShowCategoryCustomListScreen 部分源码: void ShowCategoryCustomListScreen(...,U8 * guiBuffer)  { //...      //根据 MMI_CATEGORY_CUSTOM_LIST 的 guiBuffer,为全局结构体变
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传
相似文档                                   自信AI助手自信AI助手

当前位置:首页 > 教育专区 > 职业教育

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2025 宁波自信网络信息技术有限公司  版权所有

客服电话:4009-655-100  投诉/维权电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服