网站首页 > 技术文章 正文
1 GDD消息系统概述
消息系统在整个系统中的关系层次如图所示:
每个主窗口均会有一个消息队列,在调用CreateWindow函数创建主窗口时内部会创建一个该主窗口所属的消息队列,消息队列长度为32。子窗口通过主窗口的消息队列获取消息。
2 同步消息与异步消息
消息发送方式分为同步发送与异步发送两种,系统提供两个API函数:SendMessage,PostMessage,分别用于两种不同的消息发送方式,它们的区别如下:
SendMessage:用于同步消息发送,消息直接发送到目标窗口的窗口过程函数中,直到该条消息被窗口过程函数处理完成后,该函数才会返回。
PostMessage:用于异步消息发送,消息发送到目标窗口所属的消息队列中后,不等待处理完成,便立即返回。
3 消息队列及消息循环与窗口的关系
因为异步消息不需要立即处理,所有主窗口和桌面窗口,都有自己的消息队列,用于缓存异步消息。对子窗口发送异步消息时,实际是将消息发送到了它所属的主窗口消息队列中。在窗口入口函数中,调用GetMessage函数从主窗口消息队列中取出一条消息,若成功取出一条消息,则调用DispatchMessage函数派发该消息,所谓派发消息其实就是间接调用主窗口的窗口过程函数处理该消息。在窗口入口函数中获取消息及派发消息实例代码如下:
while(GetMessage(&msg,hwnd)) //从指定的主窗口消息队列中取出一条消息
{
DispatchMessage(&msg); //派发该消息
}
4 窗口过程函数及消息数据结构
所有的成功发送出来的消息,无论是同步还是异步方式发送,最终都会到达窗口过程函数中,窗口过程函数是一个由用户指定的回调函数,这里也是窗口程序的主体部分,用户在这里可以对接收到的各类消息进行响应处理,对于某些不需要处理的消息必须调用DefWindowProc函数,将该消息交给系统默认处理。窗口过程函数会传入当前接收到的消息数据结构。该数据结构如下:
typedef struct tagMSG
{
HWND hwnd;
u32 Code;
u32 Param1;
u32 Param2;
const void* ExData;
}MSG;
该结构各成员作用如下:
hwnd: 该条消息所属的目标窗口句柄,窗口过程函数必然是所属该窗口;
Code: 消息代码值;
Param1: 消息参数1,不同消息代码,该参数意义不同;
Param1: 消息参数2,不同消息代码,该参数意义不同;
ExData: 消息扩展数据,不同消息代码,该参数意义不同。
上面已提及窗口过程函数主要功能就是根据不同消息做相应的处理,遇到不需要特别处理的消息交给系统做默认处理,一个典型的窗口过程函数实例代码如下:
static u32 win_proc(MSG *pMsg)
{
HWND hwnd;
HDC hdc;
RECT rc,rc0;
hwnd =pMsg->hwnd;
switch(pMsg->Code)
{
case MSG_CREATE:
GetClientRect(hwnd,&rc0);
CreateWindow(BUTTON,L"关闭",WS_CHILD|BS_NORMAL|WS_BORDER|WS_VISIBLE,RectW(&rc0)-64,RectH(&rc0)-28,60,24,hwnd,IDB_CLOSE,NULL);
GDD_CreateTimer(hwnd,1,5000,TMR_START);
break;
case MSG_TIMER:
PostMessage(hwnd,MSG_CLOSE,0,0);
break;
case MSG_NOTIFY:
{
u16 event,id;
event =HI16(pMsg->Param1);
id =LO16(pMsg->Param1);
if(event==BTN_UP && id==IDB_CLOSE)
{
PostMessage(hwnd,MSG_CLOSE,0,0);
}
}
break;
case MSG_PAINT:
{
hdc =BeginPaint(hwnd);
GetClientRect(hwnd,&rc0);
SetFillColor(hdc,RGB(170,160,135));
FillRect(hdc,&rc0);
SetTextColor(hdc,RGB(0,0,0));
TextOut(hdc,2,4,wstr,-1);
EndPaint(hwnd,hdc);
}
break;
case MSG_CLOSE:
DestroyWindow(hwnd);
return 1;
case MSG_DESTROY:
PostQuitMessage(hwnd,0);
return 1;
default:
return DefWindowProc(pMsg);
}
return 0;
}
5 消息代码及参数说明
该窗口过程函数包含了对创建窗口消息(MSG_CREATE)、定时器超时消息(MSG_TIMER)、控件状态变化告知信息(MSG_NOTIFY)、绘图消息(MSG_PAINT)、关闭窗口消息(MSG_CLOSE)及销毁窗口消息等消息对应的处理方法。除了关闭窗口消息及销毁窗口消息处理方法相同,其他消息应根据应用程序实际需求编写。上述实例只是定义了部分消息处理方法,GDD还定义了其他窗口消息类型具体参见gdd.h。应用程序可根据实际需求对各消息类型做相应的处理。
系统为用户定义了一系列通用消息代码,以下是这些消息的详细说明。
MSG_CREATE: 窗口创建消息
参数:
Param1: 由CreateWindow的pdata传入。
Param2: 忽略。
说明:
该消息在窗口创建时,由CreateWindow函数产生,用户可以在该消息响应中作一些初始化的工作。
MSG_ERASEBKGND: 窗口背景重绘消息
参数:
Param1: 绘图上下文句柄。
Param2: 忽略。
说明:
在窗口重绘之前,如果有对窗口背景进行重绘的请求,那么BeginPaint函数内部将会先以同步方式发送该消息,用于先对窗口进行背景进行重绘;背景重绘请求产生的条件为:调用了InvalidateWindow函数,第二个参数 bErase为TURE;具体参考:InvalidateWindow: 设置窗口为无效状态
?????????????MSG_NCPAINT: 窗口非客户区绘制消息
参数:
Param1: 忽略。
Param2: 忽略。
说明:
当窗口非客户区需要重新绘制时(比如窗口由不可见状态变为可见状态或用户主动发送了MSG_NCPAINT消息),当窗口过程收到该消息时,指示窗口非客户区需要重新绘制,如果用户不需要自己绘制窗口非客户,可以调用DefWindowProc函数,交由系统默认处理。
MSG_PAINT: 窗口客户区绘制消息
参数:
Param1: 忽略。
Param2: 忽略。
说明:
当窗口客户区需要重新绘制时(比如窗口由不可见状态变为可见状态或用户主动发送了MSG_PAINT消息)当窗口过程收到该消息时,指示窗口客户区需要重新绘制。
MSG_TIMER: 定时器超时消息
参数:
Param1: 定时器ID。
Param2: 忽略。
说明:
当一个定时器定时时间到来时,便会发送该消息到定时器所属的窗口,如果该定时器产生的消息未被窗口处理完成,那么该定时器将不会再重复产生MSG_TIMER消息。
MSG_CLOSE: 窗口请求关闭消息
参数:
Param1: 忽略。
Param2: 忽略。
说明:
如果接收该消息,表示窗口请求关闭,用户在这里可以按实际情况处理是否要真正关闭窗口,如果用户需要继续关闭窗口,则需调用DestroyWindow函数,否则直接返回。
MSG_DESTROY: 窗口销毁消息
参数:
Param1: 忽略。
Param2: 忽略。
说明:
当用户调用了DestroyWindow函数时,会产生该消息,表示窗口需要被销毁,用户可以在这里做一些资源善后工作,然后必需调用PostQuitMessage函数来指示窗口需要退出消息循环。
MSG_NOTIFY: 控件通知消息
参数:
Param1: 低16位:控件ID;高16位:控件通知码。
Param2: 控件窗口句柄。
说明:
该消息由控件向所属的父窗口发送的消息,用于通知父窗口,控件本身发生了状态变化,通知码用于描述控件状态及其变化等,例如:
控件名称
控件码
描述
BUTTON
BTN_DOWN
按钮被按下
BTN_UP
按钮弹起
CHECKBOX
CBN_SELECTED
复选框为选中状态
CBN_UNSELECTED
复选框为未选中状态
LISTBOX
LBN_SELCHANGE
列表框当前选择项被改变
MSG_LBUTTON_DOWN: 客户区鼠标左键点击消息
参数:
Param1: 忽略。
Param2: 低16位: X坐标值; 高16位:Y坐标值; 使用客户区坐标表示。
说明:
当鼠标在窗口的客户区按下左键时,该窗口会自动收到该消息,如果是触摸屏设备的笔针点击屏幕的动作,也会产生该消息。
MSG_LBUTTON_UP: 客户区鼠标左键弹起消息
参数:
Param1: 忽略。
Param2: 低16位: X坐标值; 高16位:Y坐标值; 使用客户区坐标表示。
说明:
当鼠标在窗口的客户区松开左键时,该窗口会自动收到该消息,如果是触摸屏设备的笔针抬起的动作,也会产生该消息。
MSG_SETFOCUS: 窗口获得焦点
参数:
Param1: 忽略。
Param2: 忽略。
说明:
当调用SetFocusWindow函数时,新设置的焦点窗口,将会收到MSG_SETFOCUS消息,当窗口收到该消息时,说明该窗口已经被设置为当前焦点窗口。对于键盘产生的消息,将会自动发送到当前焦点窗口。
???????MSG_KILLFOCUS: 窗口失去焦点
参数:
Param1: 忽略。
Param2: 忽略。
说明:
当调用SetFocusWindow函数时,当前旧的焦点窗口,将会收到MSG_KILLFOCUS消息,当窗口收到该消息时,说明该窗口失去焦点。当一个窗口失去焦点后,它将不能接收到键盘产生的消息。
???????MSG_RBUTTON_DOWN: 客户区鼠标右键点击消息
参数:
Param1: 忽略。
Param2: 低16位: X坐标值; 高16位:Y坐标值; 使用客户区坐标表示。
说明:
当鼠标在窗口的客户区按下右键时,该窗口会自动收到该消息。
MSG_LBUTTON_UP: 客户区鼠标右键弹起消息
参数:
Param1: 忽略。
Param2: 低16位: X坐标值; 高16位:Y坐标值; 使用客户区坐标表示。
说明:
当鼠标在窗口的客户区松开右键时,该窗口会自动收到该消息。
MSG_MBUTTON_DOWN: 客户区鼠标中键点击消息
参数:
Param1: 忽略。
Param2: 低16位: X坐标值; 高16位:Y坐标值; 使用客户区坐标表示。
说明:
当鼠标在窗口的客户区按下中键时,该窗口会自动收到该消息。
MSG_MBUTTON_UP: 客户区鼠标中键弹起消息
参数:
Param1: 忽略。
Param2: 低16位: X坐标值; 高16位:Y坐标值; 使用客户区坐标表示。
说明:
当鼠标在窗口的客户区松开中键时,该窗口会自动收到该消息。
???????MSG_MOUSE_MOVE: 客户区鼠标移动消息
参数:
Param1: 鼠标按键状态。可能是以下值组合:
MK_LBUTTON: 鼠标左键为按下状态。
MK_MBUTTON: 鼠标中键为按下状态。
MK_RBUTTON: 鼠标右键为按下状态。
Param2: 低16位: X坐标值; 高16位:Y坐标值; 使用客户区坐标表示。
说明:
当鼠标在窗口的客户区移动时,该窗口会自动收到该消息。
MSG_NCLBUTTON_DOWN: 非客户区鼠标左键点击消息
参数:
Param1: 忽略。
Param2: 低16位: X坐标值; 高16位:Y坐标值; 使用屏幕坐标表示。
说明:
当鼠标在窗口的非客户区按下左键时,该窗口会自动收到该消息,如果是触摸屏设备的笔针点击屏幕的动作,也会产生该消息。
MSG_NCLBUTTON_UP: 非客户区鼠标左键弹起消息
参数:
Param1: 忽略。
Param2: 低16位: X坐标值; 高16位:Y坐标值; 使用屏幕坐标表示。
说明:
当鼠标在窗口的非客户区松开左键时,该窗口会自动收到该消息,如果是触摸屏设备的笔针抬起的动作,也会产生该消息。
MSG_NCRBUTTON_DOWN: 非客户区鼠标右键点击消息
参数:
Param1: 忽略。
Param2: 低16位: X坐标值; 高16位:Y坐标值; 使用屏幕坐标表示。
说明:
当鼠标在窗口的非客户区按下右键时,该窗口会自动收到该消息。
MSG_NCRBUTTON_UP: 非客户区鼠标右键弹起消息
参数:
Param1: 忽略。
Param2: 低16位: X坐标值; 高16位:Y坐标值; 使用屏幕坐标表示。
说明:
当鼠标在窗口的非客户区松开右键时,该窗口会自动收到该消息。
MSG_NCMBUTTON_DOWN: 非客户区鼠标中键点击消息
参数:
Param1: 忽略。
Param2: 低16位: X坐标值; 高16位:Y坐标值; 使用屏幕坐标表示。
说明:
当鼠标在窗口的非客户区按下中键时,该窗口会自动收到该消息。
MSG_NCMBUTTON_UP: 非客户区鼠标中键弹起消息
参数:
Param1: 忽略。
Param2: 低16位: X坐标值; 高16位:Y坐标值; 使用屏幕坐标表示。
说明:
当鼠标在窗口的非客户区松开中键时,该窗口会自动收到该消息。
MSG_NCMOUSE_MOVE: 非客户区鼠标移动消息
参数:
Param1: 鼠标按键状态。可能是以下值组合:
MK_LBUTTON: 鼠标左键为按下状态。
MK_MBUTTON: 鼠标中键为按下状态。
MK_RBUTTON: 鼠标右键为按下状态。
Param2: 低16位: X坐标值; 高16位:Y坐标值; 使用屏幕坐标表示。
说明:
当鼠标在窗口的非客户区移动时,该窗口会自动收到该消息。
MSG_KEY_DOWN: 按键按下消息
参数:
Param1: 低16位:按键值;高16位:保留。
Param2: 该按键消息产生的时间,单位为毫秒。
说明:
当键盘有按键按下时,会产生一次该消息。
???????MSG_KEY_UP: 按键弹起消息
参数:
Param1: 低16位:按键值;高16位:保留。
Param2: 该按键消息产生的时间,单位为毫秒。
说明:
当键盘有按键弹起时,会产生一次该消息。
???????PBM_SETDATA:进度条设置数据
参数:
Param1: 进度条数据结构指针。
Param2: 忽略。
说明:
无。
???????PBM_GETDATA:进度条获得数据
参数:
Param1:进度条数据结构指针。
Param2: 忽略。
说明:
无。
???????PBM_SETRANGE:进度条设置量程值
参数:
Param1:量程值。
Param2:忽略。
说明:
无。
???????PBM_GETRANGE: 进度条获得量程值
参数:
Param1:忽略。
Param2:忽略。
返回:
量程值。
说明:
无。
???????PBM_SETPOS: 进度条设置当前位置
参数:
Param1:当前位置。
Param2:忽略。
说明:
进度条当前位置值,是相对于量程值。
???????PBM_GETPOS: 进度条获得当前位置
参数:
Param1:忽略。
Param2:忽略。
返回:
当前位置。
说明:
进度条当前位置值,是相对于量程值。
LBM_ADDSTRING: 列表框增加一个字符项
参数:
Param1:项目索引值。
Param2:字符指针。
返回:
实际的项目索引值。
???????LBM_DELSTRING: 列表框删除一个字符项
参数:
Param1:项目索引值。
Param2:忽略。
返回:
忽略。
???????LBM_SETCURSEL: 列表框设置当前选择项
参数:
Param1:项目索引值。
Param2:忽略。
返回:
忽略。
说明:
当前选择项是指当前被选中的项目。
???????LBM_GETCURSEL: 列表框获得当前选择项
参数:
Param1:忽略。
Param2:忽略。
返回:
当前选择项。
???????LBM_SETTOPINDEX: 列表框设置顶部首个可见项
参数:
Param1:项目索引值。
Param2:忽略。
返回:
忽略。
说明:
列表框显示时,是丛首个可见项开始,在这前面的项目,是不会显示出来的。
???????LBM_GETTOPINDEX: 列表框获得顶部首个可见项
参数:
Param1:忽略。
Param2:忽略。
返回:
顶部首个可见项索引值。
说明:
列表框显示时,是丛首个可见项开始,在这前面的项目,是不会显示出来的。
???????LBM_GETCOUNT: 列表框获得当前项目数量
参数:
Param1:忽略。
Param2:忽略。
返回:
当前项目数量值。
???????LBM_RESETCONTENT:列表框的删除所有项目
参数:
Param1:忽略。
Param2:忽略。
返回:
忽略。
???????LBM_GETTEXTLEN:列表框获得指定项目的字符字节长度
参数:
Param1:项目索引。
Param2:忽略。
返回:
指定项目的字符字节长度。
???????LBM_GETTEXT:列表框获得指定项目的字符内容
参数:
Param1:项目索引。
Param2:输出的字符内容缓冲区。
返回:
忽略。
???????LBM_SETITEMHEIGHT:列表框设置指定项目的高度
参数:
Param1:项目索引。
Param2:高度值(像素单位)。
返回:
忽略。
???????LBM_GETITEMHEIGHT:列表框获得指定项目的高度
参数:
Param1:项目索引。
Param2:忽略。
返回:
指定项目的高度值(像素单位)。
???????LBM_SETITEMDATA:列表框设置指定项目的数据值
参数:
Param1:项目索引。
Param2:数据值;这个数据值并不会列表框内部使用,作为用户自定义使用。
返回:
忽略。
???????LBM_GETITEMDATA:列表框获得指定项目的数据值
参数:
Param1:项目索引。
Param2:忽略。
返回:
指定项目的数据值。
6 API说明
6.1 DispatchMessage: 派发消息
u32 DispatchMessage(MSG *pMsg);
头文件:
gdd.h
参数:
pMsg: 需要派发的消息。
返回值:
消息处理结果。
说明:
该函数只在主窗口消息循环中使用。
6.2 SendMessage: 以同步方式发送消息
u32 SendMessage(HWND hwnd,u32 msg,u32 param1,u32 param2);
头文件::
gdd.h
参数:
hwnd: 消息发送的目的窗口句柄。
msg: 消息代码。
param1: 消息参数1,不同消息,该参数意义不同。
param2: 消息参数2,不同消息,该参数意义不同。
说明:
该函数以同步方式发送消息,支持跨线程发送消息到指定窗口,直到该消息被窗口处理完成后,该函数才会返回。
6.3 PostMessage: 以异步方式发送消息
BOOL PostMessage(HWND hwnd,u32 msg,u32 param1,u32 param2);
头文件::
gdd.h
参数:
hwnd: 消息发送的目的窗口句柄。
msg: 消息代码。
param1: 消息参数1,不同消息,该参数意义不同。
param2: 消息参数2,不同消息,该参数意义不同。
返回值:
TRUE: 成功; FALSE: 失败。
说明:
该函数以异步该方式发送消息,支持跨线程发送消息到指定窗口,用该函数发送一条消息后,便立即返回,不会等待窗口是否处理完成。
6.4 PostQuitMessage: 异步方式发送退出消息
BOOL PostQuitMessage(HWND hwnd,u32 exit_code);
头文件:
gdd.h
参数:
hwnd: 窗口句柄。
exit_code: 用户自定义的窗口退出码。
返回值:
TRUE: 成功; FALSE: 失败。
说明:
该函数会产生一条MSG_QUIT消息,当主窗口消息循环接收到MSG_QUIT消息时,便会自动销毁主窗口,并退出消息循环,这意味着一个主窗口过程的结束。 该函数只在主窗口过程函数的MSG_DESTROY消息中使用,在其它地方使用,将可能产生不可预知的后果;详细内容可参考窗口的关闭、销毁、退出过程
6.5 PeekMessage: 以非阻塞方式获取一条消息
BOOL PeekMessage(MSG *pMsg, HWND hwnd);
头文件:
gdd.h
参数:
pMsg: 存放一条所获得的消息缓冲区。
hwnd: 主窗口句柄。
返回值:
TRUE: 成功获得了一条消息; FALSE: 没有获得消息。
说明:
从消息队列头取出一条消息,该消息将会从消息队列中删除,该函数只在主窗口入口函数中获取消息时使用。
6.6 GetMessage: 以阻塞方式获取一条消息
BOOL GetMessage(MSG *pMsg,HWND hwnd);
头文件:
gdd.h
参数:
pMsg: 存放一条所获得的消息缓冲区。
hwnd: 主窗口句柄。
返回值:
TRUE: 成功获得了一条消息; FALSE: 获得了一条MSG_QUIT消息。
说明:
该函数只在主窗口消息循环中使用。
猜你喜欢
- 2024-12-24 Excel VBA 用户窗体设置/一步一步代你设计EXCEL用户+密码登录界面
- 2024-12-24 家庭收支理财管理系统 Access数据库系统课程设计制作实例
- 2024-12-24 Qt 2D绘图:图形视图框架的事件处理与传播
- 2024-12-24 MFC界面库BCGControlBar v32.1 - 可视化管理器和主题升级
- 2024-12-24 Qt设备识别(简单的密钥生成器) qt设备管理系统
- 2024-12-24 Access开发的《财务经济管理系统》
- 2024-12-24 初级开发人员告诉我:OO 设计模式太复杂而且没用
- 2024-12-24 从零开始学Qt(89):UDP单播和广播
- 2024-12-24 Qt入门阶段之事件 qtc间期延长的临床意义
- 2024-12-24 Access窗体查询制作步骤第二课 access窗体怎么做查询按钮
- 02-21走进git时代, 你该怎么玩?_gits
- 02-21GitHub是什么?它可不仅仅是云中的Git版本控制器
- 02-21Git常用操作总结_git基本用法
- 02-21为什么互联网巨头使用Git而放弃SVN?(含核心命令与原理)
- 02-21Git 高级用法,喜欢就拿去用_git基本用法
- 02-21Git常用命令和Git团队使用规范指南
- 02-21总结几个常用的Git命令的使用方法
- 02-21Git工作原理和常用指令_git原理详解
- 最近发表
- 标签列表
-
- cmd/c (57)
- c++中::是什么意思 (57)
- sqlset (59)
- ps可以打开pdf格式吗 (58)
- phprequire_once (61)
- localstorage.removeitem (74)
- routermode (59)
- vector线程安全吗 (70)
- & (66)
- java (73)
- org.redisson (64)
- log.warn (60)
- cannotinstantiatethetype (62)
- js数组插入 (83)
- resttemplateokhttp (59)
- gormwherein (64)
- linux删除一个文件夹 (65)
- mac安装java (72)
- reader.onload (61)
- outofmemoryerror是什么意思 (64)
- flask文件上传 (63)
- eacces (67)
- 查看mysql是否启动 (70)
- java是值传递还是引用传递 (58)
- 无效的列索引 (74)