第32章emWin(ucgui)窗口管理器之回调机制
【第3版emWin教程】第44章emWin6.x窗口管理器官方实例简单讲解

【第3版emWin教程】第44章emWin6.x窗⼝管理器官⽅实例简单讲解第44章 emWin6.x窗⼝管理器官⽅实例简单讲解为了帮助⼤家更好的理解窗⼝管理器的回调和消息机制,官⽅也提供了好⼏个这⽅⾯的例⼦,本章节我们将官⽅这⼏个例⼦也跟⼤家进⾏简单讲解,进⼀步帮助⼤家更好的学习窗⼝管理器。
44.1 初学者重要提⽰44.2 官⽅WM_Redraw.c实例讲解44.3 官⽅WM_Sample.c实例讲解(含⼤量窗⼝API操作)44.4 官⽅WM_LateClipping.c实例讲解44.5 官⽅WM_Video.c实例讲解44.6 总结44.1 初学者重要提⽰1、通过实例来学习emWin是最佳的学习捷径。
2、本章节讲解的例⼦中⽤到的部分功能还没有讲解到,但是不影响⼤家学习窗⼝管理器相关的知识。
没有讲解到的知识基本都会在后⾯章节中跟⼤家讲解。
3、窗⼝管理器这块的API函数应该是emWin⼿册所有章节中函数最多的,以后需要⽤到什么功能了,查询就⾏,或者看官⽅的实例,哪个函数不理解了也可以查⼿册。
下图是中⽂版⼿册⾥⾯API函数位置:下图是英⽂版⼿册⾥⾯API函数的位置:44.2 官⽅WM_Redraw.c实例讲解这个DEMO在模拟器中的位置:主要功能介绍:这个例⼦与第43章43.3⼩节中的例⼦相似,分别演⽰桌⾯窗⼝配置了重绘操作和不配置重绘操作下,移动窗⼝的效果。
其实不光在桌⾯窗⼝上⾯移动窗⼝要重绘,其它创建的窗⼝上⾯移动是⼀样的,也需要设置重绘。
如果⽤户新窗⼝的窗⼝回调函数⾥⾯没有写重绘消息WM_PAINT,窗⼝管理器就会按照系统默认的颜⾊的进⾏重绘,如果⽤户写了WM_PAINT消息就会按照⽤户设置的进⾏重绘。
下⾯我们将这个代码分析⼀下:#include "GUI.h"#include "WM.h"/*********************************************************************** Defines************************************************************************///// Recommended memory to run the sample with adequate performance//#define RECOMMENDED_MEMORY (1024L * 5)/********************************************************************* static code**********************************************************************//********************************************************************* _cbBkWindow*/static void _cbBkWindow(WM_MESSAGE* pMsg) { //--------------(1)switch (pMsg->MsgId) {case WM_PAINT:GUI_ClearRect(0, 50, 319, 239); //--------------(2)default:WM_DefaultProc(pMsg);}}/********************************************************************* _cbWindow*/static void _cbWindow(WM_MESSAGE* pMsg) { //--------------(3)GUI_RECT Rect;switch (pMsg->MsgId) {case WM_PAINT:WM_GetInsideRect(&Rect); //--------------(4)GUI_SetBkColor(GUI_RED);GUI_SetColor(GUI_YELLOW);GUI_ClearRectEx(&Rect); //--------------(5)GUI_DrawRectEx(&Rect);GUI_SetColor(GUI_BLACK);GUI_SetFont(&GUI_Font8x16);GUI_DispStringHCenterAt("Foreground window", 75, 40);break;default:WM_DefaultProc(pMsg);}}/********************************************************************* _MoveWindow*/static void _MoveWindow(const char* pText) {WM_HWIN hWnd;int i;//// Create foreground window//hWnd = WM_CreateWindow(10, 50, 150, 100, WM_CF_SHOW, _cbWindow, 0); //--------------(6) GUI_Delay(500);//// Move foreground window//for (i = 0; i < 40; i++) {WM_MoveWindow(hWnd, 2, 2); //--------------(7)GUI_Delay(10);}//// Show text before deleting window if we have one//if (pText) {GUI_DispStringAt(pText, 5, 50);GUI_Delay(2500);}//// Delete foreground window//WM_DeleteWindow(hWnd); //--------------(8)WM_Invalidate(WM_HBKWIN); //--------------(9)GUI_Exec();}/********************************************************************* _DemoRedraw*/static void _DemoRedraw(void) {WM_CALLBACK * _cbOldBk;GUI_SetBkColor(GUI_BLACK);GUI_Clear();GUI_SetColor(GUI_WHITE);GUI_SetFont(&GUI_Font24_ASCII);GUI_DispStringHCenterAt("WM_Redraw - Sample", 160, 5);GUI_SetFont(&GUI_Font8x16);while(1) {//// Move a window over background//_MoveWindow("Background has not been redrawn"); //--------------(10)//// Clear background//GUI_ClearRect(0, 50, 319, 239);GUI_Delay(1000);//// Set callback for background window//_cbOldBk = WM_SetCallback(WM_HBKWIN, _cbBkWindow); //--------------(11)//// Move a window over background//_MoveWindow("Background has been redrawn");//// Delete callback for Background window//WM_SetCallback(WM_HBKWIN, _cbOldBk); //--------------(12)}}/*********************************************************************** Public code************************************************************************//*********************************************************************** MainTask*/void MainTask(void) {GUI_Init();//// Check if recommended memory for the sample is available//if (GUI_ALLOC_GetNumFreeBytes() < RECOMMENDED_MEMORY) {GUI_ErrorOut("Not enough memory available.");return;}_DemoRedraw();}1. 桌⾯窗⼝回调函数。
第一章:emwin介绍

第1章e m W i n介绍本期教程开始带领大家了解一下STemWin的基本知识,其实确切的讲应该叫emWin基础知识,由于教程使用的开发板是ST的微控制器,所以就把名字统一命名成STemWin(为什么叫STemWin,在下面会有详细的讲解)。
1.1 STemWin,emWin,μCGUI之间的关系1.2 SEGGER公司介绍1.3 STemWin介绍1.4 STM32F103和407跑STemWin性能测试1.5 STemWin论坛1.6 总结1.1S T e m W i n,e m W i n,μC G U I之间的关系这个放在最开头进行说明,因为很多的初学者比较的迷惑。
对于一些刚学GUI的用户来说,知道μCGUI的比较多,而不知道所谓的emWin或者STemWin。
这个并不奇怪,主要是因为大部分人只知道SEGGER公司的做的JLINK,而不知道他们还有RTOS和相关的中间件(中间件的意思就是基于RTOS的文件系统,GUI,USB主机和设备协议栈等)。
1.1.1μCGUI在国内比较火的原因μCGUI在国内前几年比较火的原因有三点:●一个是μCOS-II在国内的推广,自从Micrum公司出的那本《嵌入式实时操作系统μCOS-II》发布之后,国内关于μCOS-II的资料就是普天盖起,再加上各种培训机构和开发板的推广,μCOS-II就在国内火起来了。
μCOS-II火的同时,它配套的中间件,特别是μCGUI就跟着在国内火了起来。
●前几年国内有一个μCGUI的论坛,这个论坛在国内的μCGUI方面应该算是做得最好的,特别是那个站长在μCGUI方面的研究,这位站长对于μCGUI在国内的发展功不可没。
●还有一个原因就是μCGUI是带有源码的,很多时候可以通过修改部分的源码实现一些特殊的功能,现在网上流传的μCGUI的源码已经不知道经过多少人的手被修改过,最原始的的代码已经在官网上面找不到了。
1.1.2emWin和μCGUI的关系首先要明白,这两个GUI是一个东西。
emwin消息机制

emwin消息机制
emWin的消息机制是其核心部分,负责处理所有在触控界面上的操作。
例如,当用户触摸一个按钮、滚动条或编辑框等控件时,都会触发窗口管理器去处理这些消息。
处理完消息后,会跳转到窗口回调函数的相应部分,在这些部分中添加所需的功能。
emWin的窗体管理基本框架也是基于窗体消息处理机制,即对窗体内的事务处理都是将各个事件作为窗体消息来响应执行。
例如,当程序首次启动或者窗口被移动时,系统就会触发WM_PAINT消息以重绘页面。
emWin的消息机制不仅包括了消息结构与类型的概念,还涉及到窗口回调机制的应用。
通过这样的机制,可以高效地处理各种用户交互事件,并实现相应的功能。
uCGUI(emWin)的应用与移植

uCGUI(emWin)的应用与移植uC/GUI(emWin)的应用与移植 2006-11-19 01:38当你开始使用emWin进行编程时,通常遵循以下的步骤:第1步:配置emWin第一步通常是通过修改头文件LCDConf.h来配置emWin。
LCDConf.h中的宏定义描述了LCD显示部分硬件特性;根据你的具体情况修改这些宏定义(例如显示屏的长、宽,每像素点用几位表示,LCD控制器的类型等参数)。
第2步:定义LCD的底层驱动函数底层函数包括对LCD(控制器)的初始化函数,LCD显示缓冲区的读写函数等,完成对LCD显示硬件的直接操作。
对于映射在系统存储器上的LCD,对显示缓冲区的操作仅需要在LCDConf.h中进行定义就可以了。
但对于采用I/O端口/缓冲区操作的LCD,就必须定义相应的接口函数了。
第3步:编译,链接和测试例子代码emWin对于单任务和多任务环境下的应用都提供了例子代码。
在编程之前,对这些例子代码进行编译、链接和测试,使你能够初步了解这些代码的使用。
第4步:修改例子程序对例子代码作少量的修改。
逐步添加一些额外的指令,例如显示不同大小的文字,显示多行等等,从而进一步理解代码的应用。
第5步:emWin的多任务应用,加入到你的操作系统中如果你的系统有可能多个任务同时对显示进行操作,这时就要用到GUITask.C文件中的GUI_MAXTASK和GUI_OS宏。
第6步:采用emWin编写你自己的应用到这一步你应该对怎样使用emWin有一个清楚的了解了。
考虑如何采用emWin提供的函数来构建你的应用,并通过阅读手册来获得各函数更详细的功能和使用上的信息。
emWin的移植移植是指对emWin进行配置和修改,使它能够在你的目标系统上运行。
参考第3.4节中的第一步和第二步,移植工作主要是针对配置头文件中的宏定义进行修改。
这些宏包括:1. LCD宏,定义了显示的尺寸和一些可选择的特性(例如镜像,等等)2.LCD控制器宏,定义了怎样对控制器进行操作。
第39章emWin(ucgui)对话框基础知识

经过初始化的对话框现在如下所示,所有小工具都包含了它们各自的初始值:
第4页 共6页
STM32-V5 开发板 STemWin 教程
39.2.4 定义话框行为
一旦对话框得到初始化,则剩下的所有工作便是向对话框过程函数添加代码,这样可定义小工具的行为, 从而使其能充分操作。继续同一个示例,最终的对话框过程函数如下所示:
创建对话框后,所有资源表中的控件都将可见。尽管这些控件在上面的屏幕截图中可见,但它们是以 “空” 的形式出现的。这是因为对话框过程函数尚未包含初始化单个元素的代码。控件的初始值、由它们所引起的 行为以及它们之间的交互作用都需要在对话框过程中进行定义。
第3页 共6页
39.2.3 初始化对话框
STM32-V5 开发板 STemWin 教程
第1页 共6页
39.1.3 对话框过程函数
STM32-V5 开发板 STemWin 教程
对话框就是一个窗口,它接收消息的方式与系统中其他所有窗口一样。大多数消息由对话框的窗口回调 程序自动处理,而其他消息则传递到建立对话框时所指定的回调程序,这便称为对话框过程函数。
39.1.4 对话框消息
发送到对话框过程函数的两种附加消息为:WM_INIT_DIALOG 和 WM_NOTIFY_PARENT。在显示对 话框前,WM_INIT_DIALOG 消息会立即发送到对话框过程函数。对话框过程函数通常使用该消息来初始化 控件,并执行其他任何会影响对话框外观的初始化任务。 WM_NOTIFY_PARENT 消息则通过对话框的子窗 口发送到对话框,通知任何事件的父窗口以确保同步化。通过子窗口发送的事件取决于其类型,并针对每个 类型的控件单独记录。
39. 1 对话框的基本原理 39. 2 创建对话框 39. 3 对话框 API 39. 4 总结
emWin522(uCGUI)图形用户接口移植详细实例_STM32_2013_12_30

emWin 5.22 (uCGUI) 图形用户接口移植实例——STM32作者:Ach日期:2013年12月29日联系方式:ox000008@1.概要移植图形用户接口的好处是不言而喻的。
本文图文并茂地介绍了一个emWin 5.22(uCGUI)的移植实例。
文章具体分为emWin简介,硬件平台简介,开发环境及项目简介,移植过程以及总结几个部分。
2.emWin简介emWin是一种高效的而图形用户界面,是我们能够摆脱处理器和显示控制器而更专注于GUI的设计。
这里借用STemWin的一幅图来说明emWin的作用和结构。
它通过LCD及GUI的配置来驱动底层硬件,而应用程序又是通过调用emWin来实现各种GUI。
5.22版的emWin带有许多常用的显示控制器的驱动(在参考手册Display Driver一章中有详细介绍),因此为我们移植带来了诸多方便。
emWin的更详细的内容可参照它的参考手册。
图1. emWin在项目中的结构3.硬件平台简介笔者使用的是一块以STM32F103VET6为核心的ARM开发板,没有外部的SRAM及Flash。
显示屏为2.8”320*240的彩色液晶屏,屏的驱动芯片为ILI9341(emWin 5.22带有它的驱动)。
屏与CPU 的连接方式为该ARM核心所特有的FSMC_SRAM方式,访问LCD内容时操作就如同读写SRAM一样方便。
如果你想使用其它硬件平台来移植emWin,本文亦有一定的参考价值。
希望本文能助你成功移植emWin。
图2. 硬件平台4.开发环境简介笔者所使用的开发软件为MDK-ARM 4.70。
项目模板使用的是STemWin库中的(可从ST官方下载)。
图3. 项目截图如图,项目下面有3个文件夹,其中Appli存放的是应用层的程序,第二个文件夹就如文件名,存放了emWin5.22所有部件,第三个文件夹存放了一些STM32及其它的库。
具体见附件。
5.移植过程有了MDK-ARM以及STemWin库,整个移植过程应该比较简单。
uCGUI使用

uCGUI使用最好多参考几篇文章,比如UC/GUI中文手册与emWin5_UM_SC0:画图函数GUI_DrawRect:在当前窗口中的指定位置绘制矩形(不填充,画线颜色为前景色)void GUI_DrawRect(int x0, int y0, int x1, int y1); GUI_FillRect:在当前窗口中的指定位置绘制填充的矩形区域(填充前景色)GUI_ClearRect:清除矩形区域(为矩形区域填充背景颜色,图形界面用填充背景色达到清除屏幕的效果)1:存储设备不使用存储设备时,绘制操作直接写入显示器。
屏幕在执行绘制操作时随时更新,从而在进行各种更新时使屏幕闪烁。
如果在此过程中使用存储设备,则所有绘制操作都在存储器中执行。
仅在所有操作都完成后才将最终结果显示在屏幕上,其优点是没有闪烁。
如果不使用存储设备,则可以看到一步步的绘制操作效果,缺点是会出现显示器闪烁。
使用存储设备时,一次可见到所有例程的效果,就象单次操作一样,不能实际看见中间步骤。
以下例程是在使用存储设备时通常会调用的,基本用法非常简单:1. 创建存储设备(使用GUI_MEMDEV_Create() )。
2. 激活它(使用GUI_MEMDEV_Select() )。
3. 执行绘制操作。
4. 将结果复制到显示器中(使用GUI_MEMDEV_CopyToLCD() )。
5. 不再需要它时,删除该存储设备(使用GUI_MEMDEV_Delete() )。
2:WM窗口管理器回调例程:回调例程由用户程序定义,指示在特定事件出现时图形系统调用特定的函数。
它们通常用于在窗口内容更改时自动重绘窗口。
窗口管理器的默认特性是向每个需要重绘的窗口发送一条 WM_PAINT 。
当用户对窗口有操作时,WM会发送相应的消息给该窗口,窗口可通过回调函数根据消息直接对屏(没有用存储设备时)或对窗口的存储设备进行操作再拷贝到屏幕上,具体的消息说明可以参考emWin的中文手册。
第34章emWin(ucgui)窗口管理器实例(一)

第34章窗口管理器实例(一)为了帮助大家更好的理解窗口管理器的回调和消息机制,本期教程专门做了三个相关的例子,帮助大家更好的理解。
34. 1 用户自定义消息类型实例34. 2 桌面窗口回调函数实例34. 3 官方WM_Redraw.c实例34. 4 总结34.1用户自定义消息类型实例这里用上期教程所介绍的自定义消息类型做一个实例。
代码跟上期教程的三个实例类似。
实现源码如下(可以直接将代码复制到模拟器或者开发板上面运行)。
#include <stddef.h>#include "GUI.h"#include "DIALOG.h"#include "WM.h"#include "BUTTON.h"#include "CHECKBOX.h"#include "DROPDOWN.h"#include "EDIT.h"#include "FRAMEWIN.h"#include "LISTBOX.h"#include "MULTIEDIT.h"#include "RADIO.h"#include "SLIDER.h"#include "TEXT.h"#include "PROGBAR.h"#include "SCROLLBAR.h"#include "LISTVIEW.h"#define WM_UPDATE WM_USER + 1(1)/*********************************************************************** static data************************************************************************/GUI_COLOR _acColor[3] = {GUI_BLUE,GUI_RED,GUI_YELLOW};static char ucBackColor;/*********************************************************************** Dialog resource** This table conatins the info required to create the dialog.* It has been created by ucGUIbuilder.*/static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] = {{ FRAMEWIN_CreateIndirect, "armfly", 0, 0, 0, 800,480,FRAMEWIN_CF_MOVEABLE,0}, { BUTTON_CreateIndirect, "BUTTON0", GUI_ID_BUTTON0, 82, 122,162,37, 0,0},{ BUTTON_CreateIndirect, "BUTTON1", GUI_ID_BUTTON1, 357,123,152,35, 0,0}};/******************************************************************* FunctionName:void PaintDialog(WM_MESSAGE * pMsg)** Function: to initialize the Dialog items**** call this function in _cbCallback --> WM_PAINT*****************************************************************/void PaintDialog(WM_MESSAGE * pMsg){WM_HWIN hWin = pMsg->hWin;GUI_SetBkColor(_acColor[ucBackColor]);GUI_Clear();}/******************************************************************* FunctionName:void InitDialog(WM_MESSAGE * pMsg)** Function: to initialize the Dialog items**** call this function in _cbCallback --> WM_INIT_DIALOG*****************************************************************/void InitDialog(WM_MESSAGE * pMsg){WM_HWIN hWin = pMsg->hWin;////FRAMEWIN//FRAMEWIN_SetFont(hWin,&GUI_Font24B_ASCII);FRAMEWIN_SetTextAlign(hWin,GUI_TA_VCENTER|GUI_TA_CENTER);FRAMEWIN_AddCloseButton(hWin, FRAMEWIN_BUTTON_RIGHT, 0);FRAMEWIN_AddMaxButton(hWin, FRAMEWIN_BUTTON_RIGHT, 1);FRAMEWIN_AddMinButton(hWin, FRAMEWIN_BUTTON_RIGHT, 2);FRAMEWIN_SetTitleHeight(hWin,30);/* 默认颜色取*/ucBackColor = 0;}/*********************************************************************** Dialog callback routine*/static void _cbCallback(WM_MESSAGE * pMsg){int NCode, Id;WM_HWIN hWin = pMsg->hWin;switch (pMsg->MsgId){case WM_UPDATE: (2)ucBackColor++;if (ucBackColor == 3){ucBackColor = 0;}WM_InvalidateWindow(hWin);break;case WM_MOUSEOVER:break;case WM_PAINT:PaintDialog(pMsg);break;case WM_INIT_DIALOG:InitDialog(pMsg);break;case WM_KEY:switch (((WM_KEY_INFO*)(pMsg->Data.p))->Key) {case GUI_KEY_ESCAPE:GUI_EndDialog(hWin, 1);break;case GUI_KEY_ENTER:GUI_EndDialog(hWin, 0);break;}break;case WM_NOTIFY_PARENT:Id = WM_GetId(pMsg->hWinSrc);NCode = pMsg->Data.v;switch (Id){case GUI_ID_OK:if(NCode==WM_NOTIFICATION_RELEASED)GUI_EndDialog(hWin, 0);break;case GUI_ID_CANCEL:if(NCode==WM_NOTIFICATION_RELEASED)GUI_EndDialog(hWin, 0);break;case GUI_ID_BUTTON0:switch(NCode){case WM_NOTIFICATION_CLICKED:ucBackColor++;if (ucBackColor == 3){ucBackColor = 0;}WM_InvalidateWindow(hWin); break;case WM_NOTIFICATION_RELEASED:break;case WM_NOTIFICATION_MOVED_OUT:break;}break;case GUI_ID_BUTTON1:switch(NCode){case WM_NOTIFICATION_CLICKED:ucBackColor--;if (ucBackColor < 0){ucBackColor = 2;}WM_InvalidateWindow(hWin);break;case WM_NOTIFICATION_RELEASED:break;case WM_NOTIFICATION_MOVED_OUT:break;}break;}break;default:WM_DefaultProc(pMsg);}}/*********************************************************************** MainTask************************************************************************/void MainTask(void){WM_HWIN hDlg;GUI_Init();WM_SetDesktopColor(GUI_BLUE); /* Automacally update desktop window */WM_SetCreateFlags(WM_CF_MEMDEV); /* Use memory devices on all windows to avoid flicker */ PROGBAR_SetDefaultSkin(PROGBAR_SKIN_FLEX);FRAMEWIN_SetDefaultSkin(FRAMEWIN_SKIN_FLEX);PROGBAR_SetDefaultSkin(PROGBAR_SKIN_FLEX);BUTTON_SetDefaultSkin(BUTTON_SKIN_FLEX);CHECKBOX_SetDefaultSkin(CHECKBOX_SKIN_FLEX);DROPDOWN_SetDefaultSkin(DROPDOWN_SKIN_FLEX);SCROLLBAR_SetDefaultSkin(SCROLLBAR_SKIN_FLEX);SLIDER_SetDefaultSkin(SLIDER_SKIN_FLEX);HEADER_SetDefaultSkin(HEADER_SKIN_FLEX);RADIO_SetDefaultSkin(RADIO_SKIN_FLEX);/* 创建一个对话框 */hDlg = GUI_CreateDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), &_cbCallback, 0, 0, 0);while (1){WM_SendMessageNoPara(WM_GetClientWindow(hDlg), WM_UPDATE); (3)GUI_Delay(500);}}1.定义一个用户消息WM_UPDATE。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第6页 共6页
32.2.6 自动使用存储设备
窗口管理器的默认特性是向每个需要重绘的窗口发送一条 WM_PAINT。这会导致闪变效应。为抑制这 些每个窗口的闪变效应,可为重绘操作自动使用存储设备。方法为,在创建窗口时设置标记 WM_CF_MEMDEV 、 使 用 函 数 WM_SetCreateFlags() 设 置 默 认 创 建 标 记 , 或 使 用 函 数 WM_EnableMemdev()。WM 然后会将 WM_PAINT 消息输出重定向到存储设备中,再复制到显示器中。 如果整个窗口的内存不够,会自动使用分段。存储设备只是临时使用,在绘制操作完成后会移除。
裁剪是将输出限制为一个窗口或窗口一部分的过程。 窗口的裁剪区域是其可见区域。它是窗口区域减去被更高 Z 轴阶层的同属窗口遮挡的区域,然后减去 没有放入父窗口可见区域的任何部分。 坐标 坐标通常是 2 维坐标,以像素单位表示。坐标由 2 个值组成。第一个值指定水平分量 (也称为 x 坐 标),第二个值指定垂直分量 (也称为 y 坐标)。 桌面坐标 桌面坐标是桌面窗口的坐标。显示器的左上角位置 (原点)为(0,0)。 桌面窗口 桌面窗口由窗口管理器自动创建,并且始终覆盖整个显示区域。它始终是最底层的窗口,在没有定义 其他窗口时,它是默认 (活动)窗口。所有窗口都是桌面窗口的后代窗口 (子窗口、孙窗口等)。 句柄 创建新窗口后,WM 会分配一个称为句柄的唯一标识符。句柄用于在该特定窗口中执行的其他任何操 作。 隐藏/显示窗口 隐藏的窗口不可见,尽管仍然存在 (有一个句柄)。创建窗口时,如果不指定创建标记,默认情况下 是隐藏的。显示窗口使其可见,隐藏窗口则使其不可见。 父坐标 父坐标是与父窗口相关的窗口坐标。窗口的左上角位置 (原点)为(0,0)。 透明性 具有透明区域的窗口包含不与窗口其余部分一起重绘的区域。这些区域就象其背后窗口“透过”它们 显示一样。在此情况下,在有透明区域的窗口之前重绘背后窗口非常重要。WM 自动按正确的顺序进行重 绘。 有效化/无效化 有效窗口是不需要重绘的完全更新窗口。 无效窗口不会反映所有更新,因此需要完全或部分重绘。作出的更改影响了特定窗口时,WM 将该窗 口标记为无效。下次窗口重绘时 (手动或通过回调例程),将进行验证。 窗口坐标 窗口坐标是窗口的坐标。窗口的左上角位置 (原点)为(0,0)。 Z 位置, 底部/顶部
32.2.3 背景窗口重绘和回调
初始化窗口管理器期间,会创建一个包含整个 LCD 区域的窗口作为背景窗口。此窗口的句柄为 WM_HBKWIN。WM 不会自动重绘背景窗口的区域,因为没有默认的背景颜色。也就是说如果创建了另一 个窗口然后将其删除,则删除的窗口仍然可见。需要指定例程 WM_SetDesktopColor()以便为重绘背景窗 口设置颜色。也可设置回调函数来处理此问题。如果如前所述创建然后删除了一个窗口,则回调例程将触发 WM 来确认背景窗口不再有效,并自动重绘它。后面会专门的做个例子给大家讲解这个问题。
当前正用于绘制操作的窗口称为活动窗口,不一定就是最上面的窗口。 回调函数
回调函数由用户程序定义,指示在特定事件出现时图形系统调用特定的函数。它们通常用于在窗口内 容更改时自动重绘窗口。 子窗口/父窗口, 同属窗口
子窗口是相对于其他窗口(称为父窗口)定义的。只要父窗口移动,其子窗口就会相应移动。子窗口
32.2.4 无效化
无效化窗口或窗口的一部分会告诉 WM 该窗口的无效区域在下次调用 GUI_Exec()或 GUI_Delay()时应 重绘。emWin 的无效化例程不会重绘窗口的无效部分,只管理窗口的无效区域。 窗口的无效区域
第4页 共6页
STM32-V5 开发板 STemWin 教程
对于每个窗口,WM 只使用一个矩形来存储包含整个无效区域的最小矩形。例如,如果左上角的一小 部分和右下角的一小部分变为无效,则整个窗口即无效。 使用无效化的原因
使用 STemWin 窗口管理器(Window Manager)时,显示器上出现的任何内容都包含在窗口中– 屏幕 上的一个矩形区域。窗口可以为任何尺寸,并且可在屏幕上一次显示多个窗口,甚至部分或整个窗口在其他 窗口的前面也可。
窗口管理器提供一组例程,利用这些例程可以很容易地对窗口进行创建、移动、调整大小,另外还能 操控任意数量的窗口。它还通过管理显示器中窗口的分层来提供更低级别的支持,并通过提醒应用程序来显 示影响其窗口的更改。
第3页 共6页
STM32-V5 开发板 STemWin 教程
明窗口不必重绘整个无效区域;它可让窗口区域部分不受影响。此不受影响的区域然后会变成透明。WM 发送 WM_PAINT 消息到透明窗口之前,以下区域已经重绘 (通过发送一条 WM_PAINT 消息到下 面窗口)。 警示:处理 WM_PAINT 时,不得执行某些操作
32.2 回调机制,无效化和渲染
WM 可在有或无回调例程时使用。大多数情况下,最好使用回调。 STemWin 为窗口和窗口对象 (小工具)提供回调机制的根本概念是一个事件驱动系统。因为在大多 数窗口式系统中,其原理是控制流不仅仅是从用户程序到图形系统,而且还从用户程序到图形系统,然后再 通过用户程序提供的回调例程返回用户程序。此机制通常称为 “好莱坞原则”(“不要打电话给我们,我们 会给你打电话的!”),窗口管理器需要它的主要目的是触发窗口重绘。这与传统编程相反,但是它能利用窗 口管理器的无效化逻辑。
函数的一部分。
回调例程必须具有以下原型:
原型
void callback(WM_MESSAGE * pMsg);
参数
描述
pMsg
指向类型 WM_MESSAGE 的数据结构指针。
回调函数执行的操作取决于其收到的消息类型。上述原型通常后跟一个 switch 语句,它使用一个
或多个 case 语句为不同消息定义不同的行为 (通常至少是 WM_PAINT)。
使用窗口无效化而非立即重绘每个窗口的优点是只绘制窗口一次,即使其被无效化多次。例如,如果 窗口的多个属性需要更改(如背景颜色、字体和窗口大小),与所有属性都更改后重绘一次窗口相比,每个 属性更改后立即重绘窗口需要更多的次数。 重绘无效窗口
函数 GUI_Exec()重绘所有无效窗口。这通过向每个无效窗口发送一条或多条 WM_PAINT 消息完成。 大家不要小看上面讲的这几个概念,非常重要
32. 1 术语说明 32. 2 回调机制,无效化和渲染 32. 3 总结
32.1 术语说明
窗口是矩形的,由其原点(左上角的 X 和 Y 坐标)以及 X 和 Y 值(分别为宽度和高度)定义。STemWin 中的窗口:特性如下: 是矩形的。 具有 Z 位置。 可以隐藏或显示。 可具有有效和/或无效区域。 可以透明或不透明。 可以具有或不具有回调例程。 下面讲的这些基础概念一定要懂!! 活动窗口
第2页 共6页
STM32-V5 开发板 STemWin 教程
尽管窗口显示在以 X 和 Y 表示的二维屏幕上,但是 WM 也管理所谓的 Z 位置或深度坐标-- 虚拟的第 三维上的位置,该坐标确定从背景到前景的位置。各窗口因此可在其他窗口之上或之下出现。将某窗口设置 为底部,会将该窗口置于其所有同属窗口(如果有)的“底部”;设置为顶部,则将其置于其同属窗口的 “顶 部”。创建窗口时,如果不指定创建标记,默认情况下设置为顶部。
32.2.1 不使用回调函数
回调例程不是必须使用的,但是如果这样做,WM 会失去管理窗口重绘(更新)的能力。也可能混合 使用,例如让有些窗口使用回调,有些不使用。当然,如果窗口不使用回调机制,则由应用程序负责更新其 内容。
32.2.2 使用回调函数
要创建带回调的窗口,必须有一个回调例程。创建窗口(cb 参数)时该例程用作 WM_CreateWindow()
第1页 共6页
STM32-V5 开发板 STemWin 教程
始终完全包含在其父窗口中,并在必要时会被裁剪。具有相同父窗口的多个子窗口被视为 “同属”窗口。 客户区
窗口的客户区就是其可用区域。如果窗口包含边框或标题栏,则客户区是内部的矩形区域。如果没有 这种边框,则客户区的坐标与窗口自身的坐标相同。 裁剪, 裁剪区域
32.2.5 渲染透明窗口
如果需要绘制透明窗口,则 WM 会自动确保在透明窗口收到 WM_PAINT 消息前绘制窗口的背景。方 法为,在向透明窗口发送 WM_PAINT 消息前,首先重绘透明窗口无效区域下面的所有窗口区域。为确保窗 口管理器能执行透明窗口的重绘,有必要响应 WM_PAINT 消息并重绘窗口。否则,不能保证透明窗口的外 观是正确的。使用透明窗口比使用不透明窗口需要更多消耗 CPU。如果需要考虑性能问题,尝试避免使用 透明窗口或许是一个选择。
32.2.8 自动使用显示驱动缓存
WM 自动使用显示驱动缓存 (如果可用)。如果可用,它会在开始绘制无效窗口前锁定缓冲。最后一
第5页 共6页
个窗口绘制完成后,WM 解锁缓存。
STM32-V5 开发板 STemWin 教程
32.3 总结
本期教程就跟大家讲这么多,有兴趣的可以在网上查找下回调相关的机制进行了解。下期教程我们会通 过消息机制的实例来进一步的了解窗口管理器。
STM32-V5 开发板 STemWin 教程
第32章 窗口管理器之回调机制
本期教程开始讲解 STemWin 的核心内容窗口管理器。通过这几期教程,大家应该明白最基本的窗口管 理器知识。了解了这些基本的通信机制后,再学习控件的使用时,就会事半功倍。本期教程的内容主要来自 官方手册,我这里只是将其总结一下,更详细的情况看英文版的手册。
处理 WM_PAINT 消息
窗口收到 WM_PAINT 消息时,应重绘自身。将此消息发送到窗口前,WM 确保它已被选定。
非透明窗口 (默认!)必须重绘其整个无效区域。
最简单的方式是重新着色窗口的整个区域。WM 的裁剪机制确保了仅重绘无效区域。为了加速绘制过
程,仅重绘无效区域非常有用。本章稍后描述了如何获得无效区域 (信息是消息的一部分)。另一方面,透