配色: 字号:
MTK_层的基础知识
2012-08-06 | 阅:  转:  |  分享 
  
1.gdi_layer_clear()----将整个层刷成单一颜色(层激活后要立即执行)。

2.gdi_layer_set_source_key()-----将某一颜色设为层的通透色,在层合并的时候,系统会自动将层与通透色相同的颜色忽略掉(就是说这一点上看到的是底下层的颜色)gdi_layer_set_source_key(TRUE,GDI_COLOR_BLUE);

3.gdi_layer_create(20,20,136,130,&my_layer);----用来创建层,其前四个参数指出层的位置及大小(位置是以实际屏幕左上角为原点的),最后一个参数时刚创建的层句柄地址,用以返回所创建的层。(要注意一点的是,应为创建层时系统要为其分配动态内存空间,而系统保留的内存一般只够创建一个UI_device_widthUI_device_height大小的层,所以如果调用gdi_layer_create时内存不足系统就会ASSERT。解决的办法是使用函数gdi_layer_create_using_outside_memeory,即自己申请内存,然后作为参数传进去创建层。)

4.gdi_layer_set_active(my_layer);----任何时刻有且只能有一个层处于激活状态,所有的绘画函数都是默认画到这个层中(激活层中),所以想要在层上绘画必须先将其激活。创建层并不会自动激活,需要手动将其激活。不过,由于在多层的处理中需要在各个层之间切换激活,所以我们经常用到的是gdi_layer_push_and_set_active(gdi_handlehandle),此函数会把当前的激活层入栈而激活参数层,等到下次需要激活栈中的层时,只需要用函数gdi_layer_pop_and_restore_active()激活就可以了。

5.gdi_layer_get_base_handle(&base_layer);----获取基础层

gdi_layer_set_active(base_layer);//主动将基础层还原为激活状态

gui_BLT_double_buffer(0,0,UI_device_width-1,UI_device_height-1);

6.gui_BLT_double_buffer()----用来合并层,但在使用之前先得用gdi_layer_set_blt_layer(base_layer,my_laye,NULL,NULL);指明是哪几个层需要合并,函数gui_BLT_double_buffer能接受四个层句柄,也就是说我们系统同一时刻最多能合并四个层(当然创建的层可以不止这个数)。另外要注意参数的顺序,第一个传入的层是放在最底下的,然后依次往上码。也可以直接用函数gdi_layer_blt_(base_layer,my_laye,NULL,NULL,0,0,UI_device_width-1,UI_device_height-1);进行图层合并。效果一样。

7.gdi_layer_set_clip(40,25,100,100);---所谓剪切,就是在层中设一个限制区域,只有在这个区域中的绘画才是有效的,否则就会被自动忽略。剪切特效有两个特点:1,每个层一定有而且只能有一个剪切区域。2,剪切区域一经设置,永久生效。所有剪切区域用完后最后用gdi_layer_reset_clip还原(如不还原则有可能什么东西都画不上来)。

8.gdi_layer_set_opacity(TRUE,128);第一个参数指明要不要开启半透明效果,第二个参数是透明度的取值,范围从0至255,值越小表示透明度越高,当取值为0时就会完全被透掉,255即完全不透明。

9.gdi_layer_free(my_layer);---创建层需要为其分配内层空间,所以层用完后也要手动将其释放(切记一定要释放,否则别的程序就无法创建层了):

10.gui_lock_double_buffer();和gui_unlock_double_buffer();锁屏

11.gdi_layer_clear_background(GDI_COLOR_RED);//把背景全刷成红色

12.剪切区的使用:使用顺序:

gui_push_clip();//保存剪切区

gui_set_clip(0,0,MEEPOMENU_TEMP_LAYER_WIDTH-1,MEEPOMENU_TEMP_LAYER_HEIGHT-1);//设置剪切区

gui_pop_clip();//回复剪切区

代码使用样例:

gui_lock_double_buffer();//锁屏

gui_push_clip();//保存当前剪切区

gdi_layer_push_and_set_active(MeepoMenu_temp_layer_prev);//保存当前激活层到栈中,并激活参数(MeepoMenu_temp_layer_prev)层。

old_alpha_layer=gdi_image_abm_set_source_layer(MeepoMenu_temp_layer_prev);//设置图片在此层上通透,并返回之前的通透层

gdi_layer_set_source_key(TRUE,GDI_COLOR_TRANSPARENT);//设置通透颜色

gdi_layer_clear_background(GDI_COLOR_BLACK);//把背景刷成黑色

gui_set_clip(0,0,MEEPOMENU_TEMP_LAYER_WIDTH-1,MEEPOMENU_TEMP_LAYER_HEIGHT-1);//设置剪切区

GetMeepoMenuPageImg(meepomenu_page_prev,&img_id,&str_id);//获取要绘制的图片的id

gui_show_image(0,0,(PU8)GetImage((U16)(img_id)));

gui_show_image(0,0,(PU8)GetImage((U16)(str_id)));

gdi_layer_pop_and_restore_active();//从栈中弹出之前保存的激活层,并激活

if(old_alpha_layer)

{

gdi_image_abm_set_source_layer(old_alpha_layer);//重新设置通透层

}

gui_pop_clip();//弹出之前保存的剪切区

gui_unlock_double_buffer();//解锁











MTK一些有用的层函数





MTK的层在窗口设计中应用十分广泛,对于UI来说,没有一个窗口不是由层构成的,最基本的窗口至少也是在基层上设计的。以至于许多时候,如果对层不甚了解,连阅读代码有时也会遇到困难。我曾经写过一些有关层的使用的基础知识,由于有关这方面资料很少,许多时候只能在模拟器上打断点自己慢慢研究。



层可以在模拟器中调试,在模拟器上的TOOL菜单中的InfoMonitor功能窗口,可以看到当前窗口由哪些层和各个层显示的内容,但不包括你虽然创建了,但没有调用函数gdi_layer_blt或者与他gdi_layer_blt相类似函数刷到窗口上的层。



处理PNG有关的函数

gdi_push_and_set_alpha_blending_source_layer

gdi_pop_and_set_alpha_blending_source_layer

gdi_set_alpha_blending_source_layer

gdi_get_alpha_blending_source_layer

这一组函数是在层上绘制PNG图片时使用,是PNG函数的专用函数,可以有效还原PNG图片的效果,前两个函数是成对使用,后一个函数作用同前两个,但使用上更自由一些,如果超过两个层,每个层都要画PNG,无疑使用gdi_set_alpha_blending_source_layer更加方便。最后一个是获取BLENDING层。



设置层的位置

gdi_layer_set_position

如果层上的数据是经过十分复杂的运算过程得出来的,比如要在IDLE上显示一个可以使用手指移动的农历是日历,这时就可以在层上画好要显示的数据,通话移动层的位置实现移动效果,要比每次重绘日历要快捷的多。



合并到BASE层

gdi_layer_flatten_previous_to_base

类似的函数还有

gdi_layer_flatten

前者是把当前窗口数据合并到基层,后者是把指定的层合的激活层上,该函数常常在退出窗口时使用,如果你见有些窗口在弹出对话框时该窗口背景突然消失,那大约就是因为未使用该函数的原因。因为MTK的很多窗口都不是单一层,更关键的是在创建新窗口时有时会释放老窗口的层资源,导到在老窗口非基层的显示数据丢失。该函数使用我们可以使用超过四个层来创建更为复杂的效果。



添加DM层

dm_add_blt_layer

有时你创建了层,激活了层,在层上也绘上了图片,也调用刷屏函数了,但你总是看不到屏上显示你的层,在模拟器中的InfoMonitor窗口也看不到你的层,有时是你的层闪了一下就没影了,这时你就要研究dm_redraw_category_screen了,该函数做为大部分窗口的刷新函数,当窗口有变化时,就会执行该函数,而该函数中有一段类似如下的函数调用:

gdi_layer_blt(

dm_layers[0],

dm_layers[1],

dm_layers[2],

dm_layers[3],

dm_cat_scr_info.x1,

dm_cat_scr_info.y1,

dm_cat_scr_info.x2-dm_cat_scr_info.x1-1,

dm_cat_scr_info.y2-dm_cat_scr_info.y1-1);

该调用会重新刷屏,很遗憾的是,你新创建的层不在数组dm_layers中,也就不在他刷新的范围内。要么调用dm_add_blt_layer把你的层加入,要么在dm_redraw_category_screen之后再把你自己的层刷到屏上。



使用外部内存创建层

med_alloc_ext_mem

当然类似函数也有很多,如

mmi_frm_scrmem_alloc

确切的说,这两个函数都不能算是LAYER的函数,但如果你要使用gdi_layer_create_using_outside_memory创建层,却少不了这两个函数。在这两个函数中,我们常常调用med_alloc_ext_mem来分配内存,是因为该函数能提供大约400K左右内存可供调用,而mmi_frm_scrmem_alloc可以提供200~300K内存可供调用。但随着MTK手机沦为SP赚钱工具后,使用med_alloc_ext_mem分配内存越来越不安全。在之前的一次设计中,出了问题,多亏公司一高手指点,才消灭了这一处使用的隐患。





保存层到文件

gdi_layer_save_jpeg_file

gdi_layer_save_pbm_file

gdi_layer_save_bmp_file





还有一类函数,设计窗口时可以处理层,但却不属于层函数,见一个同事使用,顺手拉来,以防忘记

dm_register_category_controlled_callback

dm_register_category_controlled2_callback

该函数会为创建的层指定绘定函数,并且这两个函数只能分别处理DM管理的层,DM管理的层及相关控件可以在结构mmi_dm_control_ids_enum找到,前一个函数处理BASE层,后一个处理新层,这两个层在g_categories_controls_map中的control_set_p中定义,control_set_p中一般会包含基层,有时也包含新层,定义如下格式

constU8categoryXXXX[]=

{

4,

DM_BASE_LAYER_START,

DM_CATEGORY_CONTROLLED_AREA,

DM_NEW_LAYER_START,

DM_CATEGORY_CONTROLLED_AREA2,

};但是在该结构中只能定义两个层,如果你想创建第三个层并使用DM管理,就要使用上面提到的dm_add_blt_layer,层的处理函数也要自己写,维护。



刷屏函数

gdi_layer_blt_previous

gui_BLT_double_buffer

gdi_layer_blt

gdi_layer_set_blt_layer

前三个函数都是刷屏函数,前两个功能一模一样,只能指定刷新的区域,使用前需要用第四个函数指定参与操作的层。第三个可以自己指定要刷到屏的层和区域。需要说明的是,执行gui_BLT_double_buffer和执行gdi_layer_blt_previous不仅效果一样,执行过程也是一样的,gui_BLT_double_buffer只是个函数指针,指向gdi_layer_blt_previous,调用他最后执行的仍然是gdi_layer_blt_previous

献花(0)
+1
(本文系小云蔡首藏)