第12章  视窗管理器(WM) 
 
使用µC/GUI 管理器(WM)时,在显示屏上显示的的所有内容包括在一个窗口里面——屏
幕上的一块区域,该区域作为一个绘制或显示对象的用户接口部件。窗口可以是任意大小,
你可能在屏幕上同时显示多个窗口,甚至在其它窗口的上面部分或完全地显示。 
视窗管理器提供了一套函数,使你能很容易地对许多窗口进行创建,移动,调整大小及
其它操作。它也可以提供更低层的支持,这通过管理显示屏上的窗口的层,及通过给你的应
用程序发送信号以显示影响它的窗口的修改来完成。 
µC/GUI 的视窗管理器是一个独立的(可选的)的软件项目,它没有包括进µC/GUI 基本
软件包里。视窗管理器的软件位于子目录“GUI\WM”下。
µC/GUI 中文手册 
第 1 页 
第 12 章  视窗管理器(WM) 
12.1  术语解释 
窗口外形是矩形,由它们的原点(左上角的 X 和 Y 坐标)及它们的 X 和 Y 尺寸(分别是
宽和高)所定义。µC/GUI 中一个窗口: 
· 是一个矩形 
· 有一个 Z 坐标 
· 可能是隐藏的或可见的 
· 可能拥有有效/或无效区域 
· 可以或者不可以有透明区域 
· 可以或者不可以有一个回调函数 
活动窗口 
当前正在使用进行绘图操作的窗口被当作活动窗口。与最顶层窗口一样,它不是必需的。 
回调函数 
回调函数在用户程序中定义,当一个指定的事件发生时,通知图形系统调用指定的函数。
通常应用于一个窗口内容改变时自动重绘的场合。 
子/父窗口,同胞 
一个子窗口的定义是相对于另一个窗口,该窗口称为父窗口。无论什么时候,一个父窗
口移动了,它的子窗口会相应随之移动。一个子窗口总是完全包含在它的父窗口里面,如果
需要,它会被剪切。从属于同一个父窗口的多个子窗口相互间的关系称为“同胞”。 
客户区 
一个窗口的客户区简单地说是它的可使用区。如果一个窗口包括一个边框或标题栏,则
客户区是内部的矩形区域。如果没有这样一个边框,则客户区等同于窗口本身。 
剪切,剪切区域 
剪切是一种限制窗口或它的部分输出的操作。 
剪切区域是一个窗口的原有可见区域。由于被更高 Z 序列的同胞窗口遮挡,或者不在父
第 2 页 
µC/GUI 中文手册 
窗口可见区域范围之内的缘故,这些部分就会被剪切掉。 
第 12 章  视窗管理器  
桌面窗口 
桌面窗口由视窗管理器自动创建,总是覆盖整个显示区域。它始终是一个最底层的窗口。
如果没有定义其它窗口,它就是默认(活动)窗口。所有窗口都是桌面窗口的继承窗口。 
句柄 
当一个新的窗口被创建,WM 会给它分配一个唯一的标识符,称为句柄。句柄将用于对特
定窗口更进一步操作的执行。 
隐藏/显示窗口 
一个隐藏的窗口是不可见的,尽管它仍然存在(有句柄)。当创建一个窗口时,如果没有
创建指定的标识的话,默认状态是隐藏。使一个窗口可见则可以将其显示;使其不可见则可
以隐藏它。 
透明 
带有透明部分的窗口包括有窗口静止时不被重绘的区域。这些区域的操作就仿佛是下面
的窗口可以透过它们显示出来。在这种情况下,下面的窗口在这个透明窗口之前重绘就显得
很重要了。WM 能自动处理正确的重绘顺序。 
有效/无效 
一个有效的窗口是一个完全更新了的窗口,它不需要重绘。 
一个无效的窗口不再对所有的更新有反应,因此需要完全或部分重绘。当改变影响一个
特定的窗口时,WM 标记该窗口无效。下一次窗口重绘(手动或通过回调函数)后,它将有效。 
Z-序,底层/顶层 
尽管一个窗口是在一个只有 X 和 Y 坐标构成的二维的屏幕上显示,WM 也管理被认为是 Z-
序,或者深度的座标——一个虚拟的三维的坐标,决定窗口从背景到前景放置。因此窗口可
以在另一窗口的上面或下面显示。 
将一个窗口设置到底层将会把它放在所有同胞窗口(如果存在)的下面;设置为顶层将
会把它放在所有同胞窗口的上面。创建一个窗口时,如果没有指定创建标识符,默认情况下
µC/GUI 中文手册 
第 3 页 
第 12 章  视窗管理器(WM) 
它会被设置在顶层。 
12.2 WM API  函数 
下表列出了与 µC/GUI 视察管理器有关的函数,在各自的类型中按字母顺序进行排列。
函数的详细描述在本章稍后列出。 
函数 
说明 
基本函数 
WM_CreateWindow() 
创建一个窗口。 
WM_CreateWindowAsChild()  创建一个子窗口。 
WM_DeleteWindow() 
删除一个窗口。 
WM_Exec() 
WM_Exec1() 
通过执行回调函数(所有工作)重绘有效窗口。 
通过执行一个回调函数(仅一个工作)重绘有效窗口。
WM_GetClientRect() 
返回活动窗口的。 
WM_GetDialogItem() 
返回一个对话框项目(控件)的窗口句柄。 
WM_GetOrgX() 
WM_GetOrgY() 
返回活动窗口的原点 X 坐标。 
返回活动窗口的原点 Y 坐标。 
WM_GetWindowOrgX() 
返回一个窗口的原点 X 坐标。 
WM_GetWindowOrgY() 
返回一个窗口的原点 Y 坐标。 
WM_GetWindowRect() 
返回活动窗口的屏幕坐标。 
WM_GetWindowSizeX() 
返回一个窗口的水平尺寸(宽度)。 
WM_GetWindowSizeY() 
返回一个窗口的垂直尺寸(高度)。 
WM_HideWindow() 
使一个窗口不可见。 
WM_InvalidateArea() 
使显示屏的某些部分无效。 
WM_InvalidateRect() 
使一个窗口部分无效。 
WM_InvalidateWindow() 
使一个窗口无效。 
WM_MoveTo() 
设置一个窗口的坐标。 
WM_MoveWindow() 
移动一个窗口到另一个位置。 
WM_Paint() 
立即绘制或重绘一个窗口。 
WM_ResizeWindow() 
改变一个窗口尺寸。 
WM_SelectWindow() 
设置用于绘图操作的活动窗口。 
WM_ShowWindow() 
使一个窗口可见。 
高级特性 
WM_Activate() 
激活视窗管理器。 
WM_BringToBottom() 
在其同胞窗口之后放置一个窗口。 
WM_BringToTop() 
在其同胞窗口之前放置一个窗口。 
WM_ClrHasTrans() 
清除 has 透明标识。 
WM_Deactivate() 
解除视窗管理器。 
WM_DefaultProc() 
处理信息的默认函数。 
第 4 页 
µC/GUI 中文手册 
第 12 章  视窗管理器  
WM_GetActiveWindow() 
返回活动窗口的句柄。 
WM_GetDesktopWindow() 
返回桌面窗口的句柄。 
WM_GetFirstChild() 
返回窗口的第一个子窗口的句柄。 
WM_GetNextSibling() 
返回窗口的下一相同胞窗口的句柄。 
WM_GetHasTrans() 
返回 has 透明标志的当前值。 
WM_GetParent() 
返回窗口的父窗口的句柄。 
WM_Init() 
WM_IsWindow() 
初始化视窗管理器。不再需要由 GUI_Init()来完成。 
判断一个指定的句柄是否一个有效句柄。 
WM_SendMessage() 
向一个窗口发送信息。 
WM_SetDesktopColor() 
设置桌面窗口颜色。 
WM_SetCallback() 
为一个窗口设置回调函数。 
WM_SetCreateFlags() 
当创建一个新窗口时设置一个默认标识符。 
WM_SetHasTrans() 
设置 has 透明标志。 
WM_SetUserClipRect() 
临时减小剪切区域。 
WM_ValidateRect() 
使一个窗口的部分有效。 
WM_ValidateWindow() 
使一个窗口有效。 
存储设备支持(可选) 
WM_DisableMemdev() 
禁止用于重绘一个窗口的存储设备的使用。 
WM_EnableMemdev() 
启用用于重绘一个窗口的存储设备的使用。 
12.3  视窗管理器的回调机制 
WM 可以在有或没有回调函数的情况下使用。在大多数情况下,使用回调函数更为可取。 
回调机制后面的哲学 
µC/GUI 为窗口和窗口对象(控件)提供的回调机制实质是一个事件驱动系统。正如在大
多数视窗系统中一样,原则是控制流程不只是从用户程序到图形系统(用户程序调用图形系
统函数来更新窗口),而且可以从用户程序到图形系统,同时也从图形系统回到用户程序,意
思是图形系统也可以调用用户程序提供的回调函数来达到更新窗口的目的。这种机制——常
常表现好莱坞法则的特点(“不要打电话给我们,我们会打电话给你们!”)——主要是视窗管
理器为了启动窗口重绘的需要。与传统程序比较有差异,但它使对视窗管理器的无效逻辑开
发成为可能。 
不使用回调函数 
你不一定非要用回调函数不可,但这样做,WM 在重绘窗口管理时会降低效率。也可以混
合使用,例如,一些窗口使用回调而另一些却不使用。然而,如果一个窗口不使用回调机制,
µC/GUI 中文手册 
第 5 页 
第 12 章  视窗管理器(WM) 
你的应用程序必须负责更新窗口内容。 
警告:当没有使用回调机制时,屏幕更新的管理就成了你的责任。 
12.4  使用回调函数 
为了使用一个回调函数创建窗口,你必需要有一个回调函数。函数的名称将与创建窗口
时对应的回调函数指针参数名称相一致(即 WM_CreateWindow() 中的 cb 参数)。所有的回调
函数必须具有以下函数原型: 
函数原型 
void callback(WM_MESSAGE* pMsg); 
参  数 
pMsg 
含  意 
消息的指针。 
回调函数的执行行为依赖于它收到的消息类型。上面的函数原型通常带有一个开关声明,
用于定义了对于不同的使用一个或更多的事件声明的消息所采用的不同的处理方式(典型的
至少有对 WM_PAINT()的处理)。 
范例 
创建一个回调函数自动重绘一个窗口: 
void WinHandler(WM_MESSAGE* pMsg)  
{ 
switch (pMsg->MsgId)  
{ 
case WM_PAINT: 
GUI_SetBkColor(0xFF00); 
GUI_Clear(); 
GUI_DispStringAt(“Hello world”,0,0); 
break; 
} 
} 
WM_MESSAGE 元素 
第 6 页 
µC/GUI 中文手册 
第 12 章  视窗管理器  
MsgId 
HWin 
消息的类型(参照下表) 
目标窗口。 
hWinSrc 
源窗口。 
Data.p 
Data.v 
数据指针。 
数据数值。 
MsgId 元素使用的消息类型 
WM_PAINT  重绘窗口(因为内容至少部分无效)。 
WM_CREATE  一个窗口创建后产即发送。 
WM_DELETE  告诉窗口释放它的数据结构(如果有的话),然后它将会被删除。 
WM_SIZE 
当一个窗口的大小改变后发送到它。 
WM_MOVE 
当一个窗口移动后发送到它。 
WM_SHOW 
当一个窗口收到显示命令后发送到它。 
WM_HIDE 
当一个窗口收到隐藏命令后发送到它。 
WM_TOUCH  触摸屏消息。 
应用程序可以为它自己的用途定义附加消息。为了保证它们使用的消息 ID 不会与µC/GUI
使用的消息 ID 同名,用户定义的消息的编号以 WM_USER 为开始。你应该像下面所展示的一样
定义你自己的消息: 
#define MY_MESSAGE_AAA  WM_USER+0  
#define MY_MESSAGE_BBB  WM_USER+1  
等等 
背景窗口重绘及回调 
在初始化视窗管理器期间,会创建一个包括整个 LCD 区域的窗口作为背景窗口(或称桌
面窗口)。该窗口的句柄是 WM_HBKWIN。WM 不会自动重绘背景窗口的区域,因为没有默认的背
景颜色。这意味着如果你进一步创建新一层窗口,然后删除它,被删除的窗口仍然是可见的。
需要指定 WM_SetBkWindowColor() 函数设置重绘背景窗口的颜色。 
你也可以设置一个回调函数处理这个问题。如果一个窗口被创建,然后象前面一样被删
除,回调函数将触发 WM 去识别背景窗口已不再有效,并自动进行重绘。想了解关于创建和使
用回调函数的信息,参考本章末的范例。 
µC/GUI 中文手册 
第 7 页 
第 12 章  视窗管理器(WM) 
12.5  基本函数 
WM_CreateWindow() 
描述 
在一个指定位置创建一个指定尺寸的窗口 
函数原型 
WM_HWIN WM_CreateWindow (  int x0, int y0, 
int width, int height, 
U8 Style, 
WM_CALLBACK* cb, 
int NumExtraBytes); 
含  意 
参  数 
x0 
y0 
左上角 X 轴坐标。 
左上角 Y 轴坐标。 
width 
窗口的 X 轴尺寸。 
height 
窗口的 Y 轴尺寸。 
Style 
窗口创建标识,如下一表格所示。 
cb 
回调函数的指针,如果没有使用回调函数则为 NULL。 
NumExtraBytes  分配的额外字节数,通常为 0。 
参数 Style 允许数值(或数值组合) 
WM_CF_HASTRANS 
Has 透明标志。必须由窗口定义哪些客户区不能完全填充。 
WM_CF_HIDE 
创建窗口后将它隐藏(默认)。 
WM_CF_SHOW 
WM_CF_FGND 
WM_CF_BGND 
创建窗口后显示它。 
创建窗口后把它放到前面。(默认)。 
创建窗口后把它放到后面。 
WM_CF_STAYONTOP  确定窗口继续停留在所有创建的不带这个标志的同胞窗口上面。 
重绘时自动使用一个存储设备。这可能避免闪烁,同时在大多数
情况下会提高输出速度,因为剪切简化了。注意为了能够使用这
个标志,要求用到存储设备软件包(并且要在配置中启用)。如
果存储设备没有启用,该标志被忽略。 
WM_CF_MEMDEV 
返回数值 
第 8 页 
µC/GUI 中文手册