MTK平台开发总结.docx
- 文档编号:5986854
- 上传时间:2023-01-02
- 格式:DOCX
- 页数:27
- 大小:85.99KB
MTK平台开发总结.docx
《MTK平台开发总结.docx》由会员分享,可在线阅读,更多相关《MTK平台开发总结.docx(27页珍藏版)》请在冰豆网上搜索。
MTK平台开发总结
声明:
前阶段进行了近两个月的MTK平台上层开发,由于缺乏技术支持,对于整个平台的认识都是通过简略的文档和浅薄的经验摸索出来的。
其间整理了一些文档。
由于联发科提供的PDF全部是英文,有些名词难以翻译准确,只能凭单方理解和嵌入式开发的词汇习惯进行意译,还请谅解。
系列文章均出自原创,肤浅可笑之处,望海涵。
(一)窗体的重画
通过观察可以发现,每个窗体模板都调用这样一个函数:
dm_redraw_category_screen()。
这个函数便是显示窗体的函数。
它内部的实现是这样的:
获得该窗体所包含的组件及它们的属性,再根据组件的类型和属性,调用不同的接口,逐一绘制各组件。
详细流程如下图所示:
由上面的流程可见,无论是窗体所包含的组件,还是组件的属性,都是根据模板ID获取的。
那么现在摆在面前的有两个问题:
一、模板ID是如何传递到这个函数中的;二、模板ID和窗体组件、组件的属性,是如何关联到一起的。
我们逐一解决这两个问题。
一、模板ID是如何传递到这个函数中的
模板ID,是ShowCategory..Screen()过程中,所显示的界面的编号,千万不要与EntryNewScreen(scrID,…)函数中传入的窗口ID相混淆。
它们以“MMI_”为前缀,被定义在枚举型结构MMI_CATEGORY_ID_LIST中,又通过结构体dm_data_struct和它的全局结构体变量g_dm_data,在应用程序中被广泛使用。
先看看结构体dm_data_struct的定义:
typedefstruct
{
S32s32ScrId;
S32s32CatId;
S32s32flags;
}
其中,s32ScrId是当前窗口ID,也就是我们使用EntryNewScreen()时传入的那个参数;而s32CatId才是模板ID;最后的flag,是模板需要显示软键盘、清屏等动作时,所置的标志变量,它在上面提到的那个dm_redraw_category_screen()函数中被判断。
还是来重点看一下第2个结构体成员s32CateId的使用。
以ShowCategory6Screen()为例。
这个显示模板的函数中,经常可以看到这样的语句:
dm_data.s32ScrId=(S32)GetActiveScreenId();
dm_data.s32CatId=MMI_CATEGORY6_ID;
dm_data.s32flags=0;
dm_setup_data(&dm_data);
再看dm_setup_data()干了什么:
voiddm_setup_data(dm_data_struct*dm_data)
{
g_dm_data.s32CatId=dm_data->s32CatId;
g_dm_data.s32ScrId=dm_data->s32ScrId;
g_dm_data.s32flags=dm_data->s32flags;
}
这样,MMI_CATEGORY6_ID就被很自然的赋到g_dm_data.s32ScrId中了,然后随着这个全局变量,顺利的被带到了dm_redraw_category_screen()中。
二、模板ID和窗体组件、组件的属性,是如何关联到一起的
通过分析dm_search_control_set函数,发现窗体模板的组件和属性相关信息都隐藏在一个宏伟的结构体数组中:
g_categories_controls_map。
这个结构体定义dm_category_id_control_set_map_struct定义如下:
typedefstruct
{
U16category_id;
U8*control_set_p;
S16*default_coordinate_set_p;
S16*rotated_coordinate_set_p;
}dm_category_id_control_set_map_struct;
第一个结构体成员,是窗体模板的ID;
第二个结构体成员,是组件数组的首地址;
第三个结构体成员,是默认的组件属性数组的首地址;
第四个结构体成员,是特殊的组件属性数组的首地址。
dm_search_control_set()函数dm_search_coordinate_set()函数就是通过匹配模板ID在结构体数组中分别获取的组件集合和组件属性集合的。
好,到这里,我们刚才提出的两个问题就明确了。
(二)构成窗体的组件的定义
根据上文可以知道,窗体组件的定义与窗体模板ID是通过结构体dm_category_id_control_set_map_struct关联的。
现在来看一看组件数组的结构。
下面将以5号模板为例。
constU8category5[]=
{
5,
DM_BASE_LAYER_START,
DM_SCR_BG,
DM_BASE_CONTROL_SET1,
DM_MULTILINE_INPUTBOX1,
DM_CATEGORY_CONTROLLED_AREA
}
在这个组件数组中,第一个字节“5”代表组件的数量;第二个字节开始就是组件的类别的ID了。
比如说,DM_BASE_LAYER_START,代表开始使用Layer;DM_SCR_BG表示背景图;DM_BASE_CONTROL_SET1表示窗体的基本组成——状态栏、标题和软按键;DM_MULTILINE_INPUTBOX1是多行输入框;DM_CATEGORY_CONTROLLED_AREA则是输入法的显示部分。
它们被定义在枚举结构mmi_dm_control_ids_enum中。
在MTK环境的原始版本中,一共有99种组件。
其后的都是用户自己扩展的。
各组件的外观和功用是什么,基本是可以见词知意的,可以在具体使用过程中了解。
(三)各组件的属性定义
仍以5号模板为例,观察组件属性数组。
cosntS16coordinate_set[]=
{
DM_FULL_SCREEN_COORDINATE_FLAG,
DM_CONTENT_COORDINATE_FLAG,
DM_FULL_SCREEN_COORDINATE_FLAG
}
这两个常量都是代表组件属性的标志。
定义在Wgui_draw_manager.h中大家可以观察到,它们都是负数:
#defineDM_FULL_SCREEN_COORDINATE_FLAG-10002
#defineDM_CONTENT_COORDINATE_FLAG-10004
现在就让我们一起分析一下它们在控件绘制中起到的作用,以及定义成负数的原因。
请回到(图1-1)。
通过比对我们可以发现,在dm_redraw_category_screen()函数流程的第6步的循环中,就是通过判断组件的ID来实现逐步绘制窗体的,如:
caseDM_MULTILINE_INPUTBOX1:
{
dm_setup_and_draw_multiline_inputbox(&UICtrlAccessPtr_p,&dm_cat_scr_info);
}
先来分析两个参数。
联系上面的程序,我们可以知道,UICtrlAccessPtr_p是作为参数传入dm_get_cat_scr_coordinates()函数中的,又作为返回值,完成进入循环前的最后一次更改的,而此前,它指向的是组件属性数组。
由于模板需要在其他组件被绘制前绘制窗体本身,因此它使用dm_get_cat_scr_coordinates()提前了解窗体的规格,而组件属性数组的第一个U16,就正是窗体的规格的标志ID:
DM_FULL_SCREEN_COORDINATE_FLAG。
根据该ID,dm_get_cat_scr_coordinates()做了分类判断,得到了指向结构体dm_cat_scr_info_struct的变量指针,其结构定义如下:
typedefstruct
{
S16x1;
S16y1;
S16x2;
S16y2;
S16flags;
}dm_cat_scr_info_struct;
很明显,结构体成员分别是:
起始、结束坐标,附加的标志。
在dm_get_cat_scr_coordinates()过后,指针UICtrlAccessPtr_p向后偏移了两个字节,指向了DM_CONTENT_COORDINATE_FLAG。
在绘制DM_BASE_LAYER_START、DM_SCR_BG、DM_BASE_CONTROL_SET1时,都不需要类似于起始位置、大小这样的属性来支持,因此它们的绘制函数dm_setup_base_layer()、dm_setup_and_draw_scr_bg()、dm_setup_and_draw_base_control_set()没有访问组件属性数组。
而多行输入控件的绘制函数dm_setup_and_draw_multiline_inputbox()、和输入法显示区域的绘制函数dm_setup_and_draw_category_controlled_area()却不约而同的调用了*UICtrlAccessPtr_p=dm_get_coordinates(*UICtrlAccessPtr_p,&dm_category_controlled_area_info)这一语句来获取组件属性。
因此,DM_CONTENT_COORDINATE_FLAG是多行输入控件的属性标志,DM_FULL_SCREEN_COORDINATE_FLAG是输入法显示区域的属性标志。
最后观察一下dm_get_coordinates()函数(参见下页的图)。
在这个函数里,对属性标志进行了判断,并最终为dm_cat_scr_info_struct结构体变量进行了赋值:
可以看到,在dm_get_coordinates()函数中,对UICtrlAccessPtr_p指向的内容,也就是某一个组件属性标志常量,进行了判断。
而后,根据不同情况对dm_coordinate_info的各成员赋了值。
因此,可以说,一个组件属性标志,就代表了一组包括组件坐标和标志在内的一组属性值。
但是,要引起注意的是,这些值都是固定的。
当组件的位置需要调整的时候,又该怎么办。
继续观察dm_get_coordinates()的代码段。
在判断了所有组件属性标志后,出现了一个else判断:
else
{
dm_coordinate_info->s16X=*UICtrlAccessPtr_p;
UICtrlAccessPtr_p++;
dm_coordinate_info->s16Y=*UICtrlAccessPtr_p;
UICtrlAccessPtr_p++;
dm_coordinate_info->s16Width=*UICtrlAccessPtr_p;
UICtrlAccessPtr_p++;
dm_coordinate_info->s16Height=*UICtrlAccessPtr_p;
UICtrlAccessPtr_p++;
dm_coordinate_info->Flags=*UICtrlAccessPtr_p;
UICtrlAccessPtr_p++;
}
也就是说,UICtrlAccessPtr_p指向的值,如果不是任何一个属性标志常量的话,它就被认为是起始X的值,然后指针将被后移2字节,下一个值被认为是起始Y的值,以此类推,直到这个dm_coordinate_info赋值完毕。
这就是自定义控件位置的方法。
如果,要定义一组默认值,就可以先在Wgui_draw_manager.h中定义常量,然后在dm_get_coordinates()加入分支,当组件属性中包含这个常量时,就将dm_coordinate_info的各结构体成员赋值。
这就是构造一个窗体模板的原理和方法。
利用这些,我们就可以利用GDI接口和GUI组件,随意的画我们自己的界面了,而不用仅仅去调用单调的ShowCategoryXXScreen()了。
本文详细说明了如何建设一个自定义列表窗体模板。
原理部分请参见《MTK平台
(1)——如何添加一个窗体模板》。
最终实现的是一个字典输入界面。
布局为:
该模板不包含业务逻辑,仅提供页面显示和InputBox框输入事件后的ListBox的Redraw事件的注册,以及基本的输入法设置、清空后的返回函数。
一、添加用户自定义列表模板的过程
(一)在g_categories_controls_map[]中加入:
{MMI_CATEGORY_CUSTOM_LIST,(U8*)custom_define_list,(s16*)coordinate_custom_list,NULL}
constU8custom_define_list[]=
{
5,
DM_BASE_LAYER_START,
DM_SCR_BG,
DM_BASE_CONTROL_SET1,
DM_SINGLELINE_INPUTBOX1,
DM_LIST1
};
constS16coordinate_custom_list[]=
{
DM_FULL_SCREEN_COORDINATE_FLAG,
DM_CUSTOM_DEFINE_INPUTBOX,//需要定义
DM_CUSTOM_DEFINE_LIST//需要定义
};
(二)在dm_get_coordinates()函数中加入:
//设定列表位置和大小(不要忘记全局变量MMI_custom_Listbox_x等的定义)
elseif(*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++;
}
//设定输入框位置和大小
elseif(*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中定义模板显示函数
voidShowCategoryCustomListScreen(
U8*title,
U16title_icon,
U16left_softkey,
U16left_softkey_icon,
U16right_softkey,
U16right_softkey_icon,
S32number_of_items,
U8**list_of_items,
U16*list_of_icons,
S32flags,
S32highlighted_item,
U8*history_buffer)
{
/*----------------------------------------------------------------*/
/*LocalVariables*/
/*----------------------------------------------------------------*/
dm_data_structdm_data;
S32i;
U8h_flag;
/*----------------------------------------------------------------*/
/*CodeBody*/
/*----------------------------------------------------------------*/
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);
//CreateList
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 { 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); } //CreateInputbox memset(custom_single_input_buffer,0,100); pfnUnicodeStrcpy(custom_single_input_buffer,L"CustomCategory"); 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(); }/*endofShowCategory353Screen*/ voidCustomList_virtual_keypad_callback(void) { #ifdefined(__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); } voidExitCategoryCustomListScreen() { wgui_close_singleline_inputbox(); } (四)在singleline_inputbox_multitap_input()函数中添加用户处理key_0~key_9的按键事件的函数: void(*singleline_inputbox_custom_input_callback)(void)=UI_dummy_function; voidsingleline_inputbox_multitap_input(UI_character_typec) { /
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- MTK 平台 开发 总结