层的运用也许是解决界面刷新,复杂界面的堆叠,代码维护最好的方法
这两天一直在研究层的概念和怎么运用它。MTK相关的资料很少,首先感谢那些肯把自己手里资料奉献出来给大家共享的人。
这里举一个简单的例子说明层的创建和运用
在这里我们创建两个层,加上基层一共三个,基层作为背景层,
MTK最多支持四个层合成,层的创建最好放在窗口里或者窗口控件里,
在退出窗口时释放~!要不会出问题的。,当然在别的地方创建也是可以的,
但要注意不能是窗口需要频繁调用的函数,因为每次创建窗口都要分配内存,
频繁调用会导致内存耗尽,退出时切记释放。该代码省略了一些与层无关的内容,比如按按键处理,触屏处理,请知悉
PU8 buf_ptr;
gdi_handle image_buffer_handle;
gdi_handle image_buffer_handle1;
gdi_handle base_handle;
#define LAYER_OPACITY 255
S32 num = 0;
extern void mmi_image_timer();
//退出释放内存函数和停止定时函数
void my_layer_exit(void)
{
gdi_layer_multi_layer_disable();
if (buf_ptr != NULL)
{
med_free_ext_mem((void **)&buf_ptr);
}
if (image_buffer_handle != NULL)
{
gdi_layer_free(image_buffer_handle);
}
if (image_buffer_handle1 != NULL)
{
gdi_layer_free(image_buffer_handle1);
}
gui_cancel_timer(mmi_image_timer);
}
//重新绘制屏幕
void redraw_my_screen()
{
gui_lock_double_buffer();
gdi_layer_set_active(image_buffer_handle);
gdi_layer_set_opacity(TRUE, 255 - num);
gdi_image_draw_id(40, 50, MAIN_MENU_VDOPLY_ICON);
gdi_layer_set_active(image_buffer_handle1);
gdi_layer_set_opacity(TRUE,num);
gdi_image_draw_id(50, 100, MAIN_MENU_AUDPLY_ICON);
gdi_layer_get_base_handle(&base_handle);
gdi_layer_set_active(base_handle);
gdi_layer_clear_background(GDI_COLOR_BLACK);
gdi_layer_set_source_key(FALSE, GDI_COLOR_BLACK);
gdi_layer_set_active(image_buffer_handle);
gdi_layer_set_source_key(TRUE, GDI_COLOR_RED);
gui_unlock_double_buffer();
gdi_layer_set_blt_layer(base_handle, image_buffer_handle, image_buffer_handle1, 0);
gdi_layer_blt_previous(0, 0, UI_device_width - 1, UI_device_height - 1);
}
//定时重复显示屏幕函数
//随便写的定时函数,有错误
//如果想得到自己的效果改下就可以了
void mmi_image_timer()
{
if(num >= LAYER_OPACITY)
{
//做NUM减小
}
redraw_my_screen();
num += 10;
gui_start_timer(100,mmi_image_timer);
}
void my_layer_entry(void)
{
U8 *gui_buffer;
BOOL isEnable;
gdi_color base_color;
//进入新的屏幕
EntryNewScreen (SCR_ID_FNG_AREA,my_layer_exit,my_layer_entry, NULL);
gui_buffer = GetCurrGuiBuffer(SCR_ID_FNG_AREA);
entry_full_screen();//全屏
gdi_layer_multi_layer_enable();//开启多层绘制
//分配内存空间,记得分配了要释放
buf_ptr = med_alloc_ext_mem(GDI_LCD_WIDTH*GDI_LCD_HEIGHT*3);
if (buf_ptr == NULL)
{
return;
}
//创建层,gdi_layer_create和gdi_layer_create_using_outside_memory是有区别的
//不做详解,望文生义可略知一二
gdi_layer_create_using_outside_memory(
0,
0,
UI_device_width,
UI_device_height,
&image_buffer_handle,
(PU8) buf_ptr,
(S32) GDI_LCD_WIDTH*GDI_LCD_HEIGHT*3);
//激活层
gdi_layer_set_active(image_buffer_handle);
//gdi_layer_clear_background(GDI_COLOR_RED);
//gdi_layer_set_source_key(TRUE, GDI_COLOR_RED);
gdi_layer_set_opacity(TRUE, 255);//设置透明度
gdi_image_draw_id(40, 50, MAIN_MENU_VDOPLY_ICON);
//同上
gdi_layer_create(0, 0, UI_device_width, UI_device_height, &image_buffer_handle1);
gdi_layer_set_active(image_buffer_handle1);
gdi_layer_clear_background(GDI_COLOR_TRANSPARENT);//刷色
gdi_layer_set_source_key(TRUE, GDI_COLOR_TRANSPARENT);//设置通透
gdi_layer_set_opacity(TRUE,0);
gdi_image_draw_id(50, 100, MAIN_MENU_AUDPLY_ICON);
//这里要激活下背景层
gdi_layer_get_base_handle(&base_handle);
gdi_layer_set_active(base_handle);
gdi_layer_clear_background(GDI_COLOR_BLACK);
gdi_layer_set_source_key(FALSE, GDI_COLOR_BLACK);
//设置最后那个为激活层,以后的绘制都在这个层上
gdi_layer_set_active(image_buffer_handle);
//得到当前活动层的通透属性
//gdi_layer_get_source_key(&isEnable, &base_color);
//设置通透
gdi_layer_set_source_key(TRUE, GDI_COLOR_TRANSPARENT);
//合并图层,注意先后顺序
gdi_layer_set_blt_layer(base_handle, image_buffer_handle, image_buffer_handle1, 0);
//刷屏
gdi_layer_blt_previous(0, 0, UI_device_width - 1, UI_device_height - 1);
//开始计时进入
gui_start_timer( 500, mmi_image_timer);
SetKeyHandler( GoBackHistory, KEY_RSK, KEY_EVENT_UP);
}
近日高仿机大行其道
丰富的视觉效果
方便的触摸操作
成了MMI设计和模仿的重中之中
当人们在尽情享受这种创意带来的便利的同时
MMI工作者却不得不去设计维护一个个功能越来越复杂,
界面越来越炫丽的令人头痛的窗口,
没有别的办法,稍一失误,就能导到整个窗口界面凌乱,功能失效,
最终使程序员不得不不把大量的时间和精力花在令人头痛的界面维护中,
在那些复杂的代码中寻找着可能的BUG
层的运用也许是解决界面刷新,复杂界面的堆叠,代码维护最好的方法
近日有不少朋友和我讨论层的使用
而MTK有关这方面的资料也确实比较少
少数几个掌握了的人又视之如珍宝
不愿轻易示人
这里举一个简单的例子说明层的创建和运用
在这里我们创建两个层,加上基层一共三个,基层作为背景层,
MTK最多支持四个层合成,层的创建最好放在窗口里或者窗口控件里,
在退出窗口时释放,要不会出问题的。,当然在别的地方创建也是可以的,
但要注意不能是窗口需要频繁调用的函数,因为每次创建窗口都要分配内存,
频繁调用会导致内存耗尽,退出时切记释放。该代码省略了一些与层无关的内容,比如按按键处理,触屏处理,请知悉
gdi_handle my_layer1, my_layer2, my_base_layer;
PU8 buf_ptr;
void exit_myapp_screen(void)
{
if (buf_ptr != NULL)
{
med_free_ext_mem((void **)&buf_ptr);
}
if (my_layer1 != NULL)
{
gdi_layer_free(my_layer1);
}
if (my_layer2 != NULL)
{
gdi_layer_free(my_layer2);
}
}
static void entry_myapp_screen(void)
{
U8 *gui_buffer;
BOOL isEnable;
gdi_color base_color;
EntryNewScreen (SCR_ID_XXXX,exit_myapp_screen,entry_myapp_screen, NULL);
gui_buffer = GetCurrGuiBuffer(SCR_ID_XXXX);
//设置窗口不带状态栏
entry_full_screen();
//开启多层
gdi_layer_multi_layer_enable();
/*该处的2等于((GDI_LCD_WIDTH*GDI_LCD_HEIGHT*GDI_MAINLCD_BIT_PER_PIXEL)>>3)
一个像素使用2个字节表示,即65536色*/
buf_ptr = med_alloc_ext_mem(GDI_LCD_WIDTH*GDI_LCD_HEIGHT*2);
if (buf_ptr == NULL)
{
//加一些错误提示
return;
}
/*从外部内存创建窗口,因为MTK提供的直接创建函数只能创建
一个层和屏幕大小一样的层*/
gdi_layer_create_using_outside_memory(
0,
0,
UI_device_width,
UI_device_height,
&my_layer1,
(PU8) buf_ptr,
(S32) GDI_LCD_WIDTH*GDI_LCD_HEIGHT*2);
//激活新层1
gdi_layer_set_active(my_layer1);
//把背景全刷成红色
gdi_layer_clear_background(GDI_COLOR_RED);
//设置红色为通透色
gdi_layer_set_source_key(TRUE, GDI_COLOR_RED);
/*在层1上画图,位置是相对层的位置,因为层大小和基层一样,
且原点和基层重合,故该座标也是相对屏幕原点的位置*/
gdi_image_draw_id(50, 100, IMG_ID_PHOART_ICON_6);
//创建层2,使用系统提供的直接创建函数从层内存直接创建
gdi_layer_create(0, 0, UI_device_width, UI_device_height, &my_layer2);
//激活新层2
gdi_layer_set_active(my_layer2);
gdi_layer_clear_background(GDI_COLOR_TRANSPARENT);//刷色
gdi_layer_set_source_key(TRUE, GDI_COLOR_TRANSPARENT);//设置通透
//在层2上输出字串
gui_move_text_cursor(50, 200);
gui_print_bordered_text(L"hellow word");
//在最后要激活基层
gdi_layer_get_base_handle(&my_base_layer);
gdi_layer_set_active(my_layer1);
//得到当前活动层的通透属性
gdi_layer_get_source_key(&isEnable, &base_color);
//设置通透
gdi_layer_set_source_key(TRUE, base_color);
//指定合并层,注意叠加的顺序
gdi_layer_set_blt_layer(my_base_layer, my_layer1, my_layer2, 0);
//刷新到屏幕上
gdi_layer_blt_previous(0, 0, UI_device_width - 1, UI_device_height - 1);
}
有关gdi_layer_create函数再说明一点,如果你通过这个函数创建的层大小比屏幕小,倒是可以创建多个的,但你所创建的层大小的总和,不能超过屏幕大小
还有一点需要注意的是,如果程序运行在仿真上,最好使用MALLOC和FREE替换med_alloc_ext_mem和med_free_ext_mem,也就是写成
#ifdef WIN32
malloc
#else
med_alloc_ext_mem
#endif
和
#ifdef WIN32
free
#else
med_free_ext_mem
#endif
MTK层相关应用集合(摘抄)2009-11-30 17:58对于层,有个核心理念:代表屏幕上像素点阵的数据集合
一般来说,MTK上一个像素由两个字节表示
一,mtk平台上旋转图像的代码,可以任意角度旋转。
void gdi_image_Rotate_Slope(double x,double y ,double dx ,double dy ,U16 IMAGE_ID,double cosn,double sinn)
{
S32 i,
j,
n,
imge_width,
imge_width2,
imge_height,
imge_height2,
transit_layer_buff_size1,
transit_layer_buff_size2;
U16* transit_layer_buff_ptr1,
* transit_layer_buff_ptr2;
U16 a,r,g,b;
gdi_handle transit_layer1,transit_layer2,last_active_layer;
S32 j2,i2;
double wb,x0,y0,x1,y1,u,v;
gdi_layer_multi_layer_enable();
gdi_image_get_dimension_id(IMAGE_ID,&imge_width,&imge_height);
transit_layer_buff_size1=((imge_width)*(imge_height)*16)>>3;
transit_layer_buff_ptr1=(U16*)mmi_frm_scrmem_alloc(transit_layer_buff_size1);
gdi_layer_create_using_outside_memory(0,0,imge_width,imge_height,&transit_layer1,(PU8)transit_layer_buff_ptr1,transit_layer_buff_size1);
gdi_layer_push_and_set_active(transit_layer1);
gdi_layer_clear(GDI_COLOR_BLUE);
gdi_layer_set_source_key(TRUE, GDI_COLOR_BLUE);
gdi_image_draw_id(0,0,IMAGE_ID);
gdi_layer_pop_and_restore_active();
imge_width2=240;
imge_height2=320;
transit_layer_buff_size2=(imge_width2*imge_height2*16)>>3;
transit_layer_buff_ptr2=(U16*)mmi_frm_scrmem_alloc(transit_layer_buff_size2);
gdi_layer_create_using_outside_memory(0,0,imge_width2,imge_height2,&transit_layer2,(PU8)transit_layer_buff_ptr2,transit_layer_buff_size2);
gdi_layer_push_and_set_active(transit_layer2);
gdi_layer_clear(GDI_COLOR_BLUE);
gdi_layer_set_source_key(TRUE, GDI_COLOR_BLUE);
for(i=0;i<imge_height2;i++)
{
for(j=0;j<imge_width2;j++)
{
x0=((double)j-x)*cosn+((double)i-y)*sinn+dx;
y0=((double)i-y)*cosn-((double)j-x)*sinn+dy;
//x0=(j-x)*cosn+(i-y)*sinn;
//y0=imge_height+(i-y)*cosn-(j-x)*sinn;
j2=(S32)x0;
i2=(S32)y0;
if((i2<(imge_height-1))&&(j2<(imge_width-1))&&(i2>0)&&(j2>0))
{
v=y0-i2;
u=x0-j2;
if(u>0.5)
j2++;
if(v>0.5)
i2++;
*(transit_layer_buff_ptr2+(i)*imge_width2+j) = *(transit_layer_buff_ptr1+i2*imge_width+j2);
}
}
}
gdi_layer_pop_and_restore_active();
gdi_layer_get_active(&last_active_layer);
gdi_layer_flatten(last_active_layer,transit_layer2,NULL,NULL);
//gdi_layer_set_blt_layer(last_active_layer,transit_layer2,NULL,NULL);
gdi_layer_free(transit_layer1);
gdi_layer_free(transit_layer2);
mmi_frm_scrmem_free(transit_layer_buff_ptr1);
mmi_frm_scrmem_free(transit_layer_buff_ptr2);
gdi_layer_multi_layer_disable();
}
有关gdi_layer_create函数再说明一点,如果你通过这个函数创建的层大小比屏幕小,倒是可以创建多个的,但你所创建的层大小的总和,不能超过屏幕大小
还有一点需要注意的是,如果程序运行在仿真上,最好使用MALLOC和FREE替换med_alloc_ext_mem和med_free_ext_mem,也就是写成
#ifdef WIN32
malloc
#else
med_alloc_ext_mem
#endif
和
#ifdef WIN32
free
#else
med_free_ext_mem
#endif
三,对于MTK平台来说,菜单和屏幕特效曾经在很长的一段时间里,影响甚远。但对于其设计过程和方法,由于各种各样的原因,很少有人提及。
这里介绍一种不同于前几天日志所载之方法的另一种方法,就是复制图层,其核心实现函数如下。
void my_gdi_layer_copy(gdi_layer_struct* dst_layer, int dst_x, int dst_y, int width, int height,
gdi_layer_struct* src_layer, int src_x, int src_y)
{
U16 *dst_buf, *src_buf;
int i;
if (dst_x < 0 || dst_y < 0 || dst_x + width > dst_layer->width || dst_y + height > dst_layer->height)
{
if (dst_x < 0)
{
width -= -dst_x;
src_x += -dst_x;
dst_x = 0;
}
if (dst_y < 0)
{
height -= -dst_y;
src_y += -dst_y;
dst_y = 0;
}
if (dst_x + width > dst_layer->width)
{
width = dst_layer->width - dst_x;
}
if (dst_y + height > dst_layer->height)
{
height = dst_layer->height - dst_y;
}
}
if (src_x < 0 || src_y < 0 || src_x + width > src_layer->width || src_y + height > src_layer->height)
{
if (src_x < 0)
{
width -= -src_x;
dst_x += -src_x;
src_x = 0;
}
if (src_y < 0)
{
height -= -src_y;
dst_y += -src_y;
src_y = 0;
}
if (src_x + width > src_layer->width)
{
width = src_layer->width - src_x;
}
if (src_y + height > src_layer->height)
{
height = src_layer->height - src_y;
}
}
if (width <= 0 || height <= 0)
return;
dst_buf = (U16 *)dst_layer->buf_ptr + dst_y * dst_layer->width + dst_x;
src_buf = (U16 *)src_layer->buf_ptr + src_y * src_layer->width + src_x;
for (i = 0; i < height; i ++)
{
memcpy(dst_buf, src_buf, width * 2);
dst_buf += dst_layer->width;
src_buf += src_layer->width;
}
}
有兴趣的朋友可以自己利用该函数研发各种各样的变化效果。
四,MTK 的层在窗口设计中应用十分广泛,对于UI来说,没有一个窗口不是由层构成的,最基本的窗口至少也是在基层上设计的。以至于许多时候,如果对层不甚了解,连阅读代码有时也会遇到困难。我曾经写过一些有关层的使用的基础知识,由于有关这方面资料很少,许多时候只能在模拟器上打断点自己慢慢研究。
层可以在模拟器中调试,在模拟器上的TOOL菜单中的Info Monitor功能窗口,可以看到当前窗口由哪些层和各个层显示的内容,但不包括你虽然创建了,但没有调用函数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
有时你创建了层,激活了层,在层上也绘上了图片,也调用刷屏函数了,但你总是看不到屏上显示你的层,在模拟器中的Info Monitor窗口也看不到你的层,有时是你的层闪了一下就没影了,这时你就要研究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找到,这两个函数可以在DM指定的层上绘图,既可以处理不同的层,也可以处理相同的层,如果不同的层,可以定义在g_categories_controls_map中的control_set_p中定义如下,control_set_p中一般会包含基层,有时也包含新层,定义如下格式
const U8 categoryXXXX[] =
{
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
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_width * UI_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_handle handle) ,此函数会把当前的激活层入栈而激活参数层,等到下次需要激活栈中的层时,只需要用函数 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();// 解锁