热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

emWin实现BMP位图皮肤之Framewin篇

(1)emWin通过skinning方式实现控件位图皮肤:1)emWin传统贴皮肤图片的方法,是调用APP函数XXXX_SetBitmap()方式实现&

(1)emWin通过skinning方式实现控件位图皮肤:

1)emWin传统贴皮肤图片的方法,是调用APP函数XXXX_SetBitmap()方式实现,但非常非常麻烦。

2)要想把控件显示出来,emWin每种控件都有1个控件绘制函数,而把这个控件绘制函数改成我们自己编写的"自定义绘制函数",这样我们想把这个控件画成什么样都行,emWin已经不参与这个控件的绘制工作了;在这个自定义绘制函数里面我们什么都不干,只显示出这个控件的图片,这就是用skinning方式实现位图皮肤。

3)支持整幅图片贴图,不需要对整幅图片进行切片分解,非常便捷。

如上图所示,(x0,y0)为整幅图片的显示坐标,(x1,y1)(x2,y2)emWin为控件自动生成的剪切显示坐标,我们只需要调用GUI_DrawBitmap()函数在(x0,y0)显示整幅图片即可,emWin会自动剪切显示出该控件的位图皮肤,功能非常强大。

 

(2)Framewin控件的自定义绘制函数:

SKIN_framewin.c

skinning.h

#include "DIALOG.h"
#include "GUI.h"
#include "skinning.h"//获取父窗口句柄,即主页面句柄,保存着页面位图的指针
static WM_HWIN WM_GetParent1C(WM_HWIN hChild) {return hChild;}
static WM_HWIN WM_GetParent2C(WM_HWIN hChild) {return WM_GetParent(hChild);}
static WM_HWIN WM_GetParent3C(WM_HWIN hChild) {return WM_GetParent(WM_GetParent(hChild));}
static WM_HWIN WM_GetParent4C(WM_HWIN hChild) {return WM_GetParent(WM_GetParent(WM_GetParent(hChild)));}
static WM_HWIN WM_GetParent5C(WM_HWIN hChild) {return WM_GetParent(WM_GetParent(WM_GetParent(WM_GetParent(hChild))));}
static WM_HWIN WM_GetParent6C(WM_HWIN hChild) {return WM_GetParent(WM_GetParent(WM_GetParent(WM_GetParent(WM_GetParent(hChild)))));}
static WM_HWIN WM_GetParent7C(WM_HWIN hChild) {return WM_GetParent(WM_GetParent(WM_GetParent(WM_GetParent(WM_GetParent(WM_GetParent(hChild))))));}
static WM_HWIN WM_GetParent8C(WM_HWIN hChild) {return WM_GetParent(WM_GetParent(WM_GetParent(WM_GetParent(WM_GetParent(WM_GetParent(WM_GetParent(hChild)))))));}
static WM_HWIN (*WM_GET_PARENT[])(WM_HWIN) = {WM_GetParent1C,WM_GetParent2C,WM_GetParent3C,WM_GetParent4C,WM_GetParent5C,WM_GetParent6C,WM_GetParent7C,WM_GetParent8C};//Framewin控件的自定义绘制函数
static int SKIN_framewin(const WIDGET_ITEM_DRAW_INFO * pDrawItemInfo, unsigned char C)
{WM_HWIN hWin;int x0, y0;WINDOW_BMP *winBMP;switch (pDrawItemInfo->Cmd){case WIDGET_ITEM_CREATE://case WIDGET_ITEM_DRAW_BACKGROUND:case WIDGET_ITEM_DRAW_FRAME:case WIDGET_ITEM_DRAW_SEP:case WIDGET_ITEM_DRAW_TEXT://case WIDGET_ITEM_GET_BORDERSIZE_L://case WIDGET_ITEM_GET_BORDERSIZE_R://case WIDGET_ITEM_GET_BORDERSIZE_T://case WIDGET_ITEM_GET_BORDERSIZE_B://case WIDGET_ITEM_GET_RADIUS:break;case WIDGET_ITEM_GET_BORDERSIZE_L:case WIDGET_ITEM_GET_BORDERSIZE_R:case WIDGET_ITEM_GET_BORDERSIZE_T:case WIDGET_ITEM_GET_BORDERSIZE_B:case WIDGET_ITEM_GET_RADIUS:return 0;case WIDGET_ITEM_DRAW_BACKGROUND:hWin = (WM_GET_PARENT[C-1])(pDrawItemInfo->hWin);//位于第几层修改这里(WM_GetParent数=层数-1)WM_GetUserData(hWin, &winBMP, sizeof(winBMP));//从用户数据区读出"页面图片结构体"指针//获取此控件相对于主页面(比如:WINDOW)位置偏移坐标x0 = WM_GetWindowOrgX(hWin) - WM_GetWindowOrgX(pDrawItemInfo->hWin);y0 = WM_GetWindowOrgY(hWin) -WM_GetWindowOrgY(pDrawItemInfo->hWin);GUI_DrawBitmap(winBMP->normal, x0, y0);//从页面坐标显示图片,emWin会自己剪切出这个控件范围的图片break;default: return FRAMEWIN_DrawSkinFlex(pDrawItemInfo);//emWin默认控件绘制函数}return 0;
}//Framewin控件的自定义绘制函数,位于第1层(比如:FRAMEWIN)
int SKIN_framewin1C(const WIDGET_ITEM_DRAW_INFO * pDrawItemInfo){return SKIN_framewin(pDrawItemInfo, 1);
}
//Framewin控件的自定义绘制函数,位于第2层(比如:WINDOW->FRAMEWIN)
int SKIN_framewin2C(const WIDGET_ITEM_DRAW_INFO * pDrawItemInfo){return SKIN_framewin(pDrawItemInfo, 2);
}
//Framewin控件的自定义绘制函数,位于第3层(比如:FRAMEWIN->CLIENT->FRAMEWIN)
int SKIN_framewin3C(const WIDGET_ITEM_DRAW_INFO * pDrawItemInfo){return SKIN_framewin(pDrawItemInfo, 3);
}
//Framewin控件的自定义绘制函数,位于第4层(比如:WINDOW->FRAMEWIN->CLIENT->FRAMEWIN)
int SKIN_framewin4C(const WIDGET_ITEM_DRAW_INFO * pDrawItemInfo){return SKIN_framewin(pDrawItemInfo, 4);
}
//Framewin控件的自定义绘制函数,位于第5层(比如:WINDOW->MULTIPAGE->CLIENT->WINDOW->FRAMEWIN)
int SKIN_framewin5C(const WIDGET_ITEM_DRAW_INFO * pDrawItemInfo){return SKIN_framewin(pDrawItemInfo, 5);
}//Multipage子页面背景重绘函数
static int SKIN_framewin_paint(WM_HWIN hPage, unsigned char C)
{WM_HWIN hWin;int x0, y0;WINDOW_BMP *winBMP;hWin = (WM_GET_PARENT[C-1])(hPage);//位于第几层修改这里(WM_GetParent数=层数-1)WM_GetUserData(hWin, &winBMP, sizeof(winBMP));//从用户数据区读出"页面图片结构体"指针//获取此控件相对于主页面(比如:WINDOW)位置偏移坐标x0 = WM_GetWindowOrgX(hWin) - WM_GetWindowOrgX(hPage);y0 = WM_GetWindowOrgY(hWin) - WM_GetWindowOrgY(hPage);GUI_DrawBitmap(winBMP->normal, x0, y0);//从页面坐标显示图片,emWin会自己剪切出这个控件范围的图片return 0;
}//Multipage子页面背景重绘函数,位于第1层(比如:FRAMEWIN)
int SKIN_framewin_paint1C(WM_HWIN hWin){return SKIN_framewin_paint(hWin, 1);
}
//Multipage子页面背景重绘函数,位于第2层(比如:WINDOW->FRAMEWIN)
int SKIN_framewin_paint2C(WM_HWIN hWin){return SKIN_framewin_paint(hWin, 2);
}
//Multipage子页面背景重绘函数,位于第3层(比如:FRAMEWIN->CLIENT->FRAMEWIN)
int SKIN_framewin_paint3C(WM_HWIN hWin){return SKIN_framewin_paint(hWin, 3);
}
//Multipage子页面背景重绘函数,位于第4层(比如:WINDOW->FRAMEWIN->CLIENT->FRAMEWIN)
int SKIN_framewin_paint4C(WM_HWIN hWin){return SKIN_framewin_paint(hWin, 4);
}
//Multipage子页面背景重绘函数,位于第5层(比如:FRAMEWIN->CLIENT->MULTIPAGE->CLIENT->WINDOW)
int SKIN_framewin_paint5C(WM_HWIN hWin){return SKIN_framewin_paint(hWin, 5);
}


(3)Skinning方式实现位图皮肤的实施步骤:

1)创建窗体时,将"页面图片结构体指针"保存于窗体中:
  WINDOW_BMP *winBMP;
  static WINDOW_BMP BMP_WIN_main;//为"Framewin"页面定义1个"页面图片结构体"
  BMP_WIN_main.normal = &bmPage2_N;//将不同状态的页面BMP位图赋值给"页面图片结构体"
  BMP_WIN_main.mark = &bmPage2_M;
  BMP_WIN_main.focus = &bmPage2_N;
  BMP_WIN_main.disable = &bmPage2_N;
  BMP_WIN_main.thumbN = &bmPage2_N;
  BMP_WIN_main.thumbM = &bmPage2_N;
  winBMP = &BMP_WIN_main;
  hWin = CreateFramewin(WM_HBKWIN);//创建Framewin页面
  WM_SetUserData(hWin, &winBMP, sizeof(winBMP));//将"页面图片结构体"指针写到用户数据区
2)在窗体初始化WM_INIT_DIALOG消息中,把FRAMEWIN控件的绘制函数改成自定义绘制函数:
  FRAMEWIN_SetSkin(pMsg->hWin, SKIN_framewin1C);//将这个FRAMEWIN控件改成自定义绘制函数
3)在FRAMEWIN控件的回调函数WM_PAINT重绘消息中,调用FRAMEWIN的背景重绘函数:
  static void _cbFramewin(WM_MESSAGE * pMsg)

  {
    switch (pMsg->MsgId) {
      case WM_PAINT: SKIN_framewin_paint2C(pMsg->hWin); break;
      case WM_INIT_DIALOG: break;
      case WM_NOTIFY_PARENT: break;
      default: WM_DefaultProc(pMsg); break;
    }
  }



(4)总结:

以整幅图片实现emWin位图皮肤应该是诺嵌光电业界首创的方法,可以大大减轻控件贴图的工作量,保守估计贴图工作效率至少提高10倍以上。如果把每个控件对应的图片先切片分解下来,然后再转换成C文件,最后再贴图到控件上面去,那样工作量将是非常恐怖的!




源码下载: \docs\demoEM\demo_emwin_CodeBlocks\skinPRJ_WINemWin530noOS_CodeBlocks_v127.rar

如何打开源码看博文:emWin 2天速成实例教程000_如何快速入门ucGUI/emWin



推荐阅读
  • This article discusses the efficiency of using char str[] and char *str and whether there is any reason to prefer one over the other. It explains the difference between the two and provides an example to illustrate their usage. ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • PHP中的单例模式与静态变量的区别及使用方法
    本文介绍了PHP中的单例模式与静态变量的区别及使用方法。在PHP中,静态变量的存活周期仅仅是每次PHP的会话周期,与Java、C++不同。静态变量在PHP中的作用域仅限于当前文件内,在函数或类中可以传递变量。本文还通过示例代码解释了静态变量在函数和类中的使用方法,并说明了静态变量的生命周期与结构体的生命周期相关联。同时,本文还介绍了静态变量在类中的使用方法,并通过示例代码展示了如何在类中使用静态变量。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • 本文介绍了深入浅出Linux设备驱动编程的重要性,以及两种加载和删除Linux内核模块的方法。通过一个内核模块的例子,展示了模块的编译和加载过程,并讨论了模块对内核大小的控制。深入理解Linux设备驱动编程对于开发者来说非常重要。 ... [详细]
  • 海马s5近光灯能否直接更换为H7?
    本文主要介绍了海马s5车型的近光灯是否可以直接更换为H7灯泡,并提供了完整的教程下载地址。此外,还详细讲解了DSP功能函数中的数据拷贝、数据填充和浮点数转换为定点数的相关内容。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • ALTERTABLE通过更改、添加、除去列和约束,或者通过启用或禁用约束和触发器来更改表的定义。语法ALTERTABLEtable{[ALTERCOLUMNcolu ... [详细]
author-avatar
骁炉
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有