windows消息机制_PostMessage和SendMessage
1.子线程中建立一个窗口
为了在后面比较这两个函数,先使用win32 windows程序中建立子线程,在子线程中建立一个窗口。
(1)新建一个 win32 windows应用程序
(2)定义子窗口的窗口响应函数
LRESULT CALLBACK SubWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_LBUTTONDOWN:
MessageBoxA(0,"","SubWndProc",0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
(3)定义子线程窗口函数
void CreateWndInThread(int nWidth, int nHeight)
{
WNDCLASSEX wcex2;
wcex2.cbSize = sizeof(WNDCLASSEX);
wcex2.style = CS_HREDRAW | CS_VREDRAW;
wcex2.lpfnWndProc = SubWndProc;
wcex2.cbClsExtra = 0;
wcex2.cbWndExtra = 0;
wcex2.hInstance = GetModuleHandle(nullptr);
wcex2.hIcon = 0;
wcex2.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex2.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex2.lpszMenuName = NULL;
wcex2.lpszClassName = L"SubWindow";
wcex2.hIconSm = 0;
RegisterClassEx(&wcex2);
HWND g_hWnd = CreateWindowA("SubWindow", nullptr,WS_OVERLAPPEDWINDOW, 0, 0, nWidth, nHeight, NULL, NULL, wcex2.hInstance, 0);
ShowWindow(g_hWnd, SW_SHOW);
UpdateWindow(g_hWnd);
MSG msg;
while (GetMessage(&msg, nullptr, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
(4)处理主线程的 WM_LBUTTONDOWN 消息
在里面开启一个子线程,调用 CreateWndInThread
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{ case WM_LBUTTONDOWN:
{
std::thread t(CreateWndInThread, 960, 480);
t.detach();
}
break;
//省略其他消息
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
(5)运行程序
在主窗口上鼠标左键点击,会创建一个子窗口,
然后在子窗口上鼠标左键点击,会弹出一个MessageBox。
可以发现两个窗口的消息处理互不影响。
2.PostMessage和SendMessage
PostMessage会将消息压入窗口所在线程的消息队列,然后立即返回,非阻塞
SendMessage则不经过消息队列,SendMessage可认为是直接调用了该窗口的窗口过程,阻塞
将上面的项目做如下修改:
(1)定义一个全局遍历来存储子窗体的句柄,定义子窗体自定义消息
#define WM_SUB_MSG (WM_USER+1)
HWND subWinHwnd;//子窗口
(2)修改子窗口的窗口响应函数
void CreateWndInThread(int nWidth, int nHeight)
{
WNDCLASSEX wcex2;
wcex2.cbSize = sizeof(WNDCLASSEX);
wcex2.style = CS_HREDRAW | CS_VREDRAW;
wcex2.lpfnWndProc = SubWndProc;
wcex2.cbClsExtra = 0;
wcex2.cbWndExtra = 0;
wcex2.hInstance = GetModuleHandle(nullptr);
wcex2.hIcon = 0;
wcex2.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex2.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex2.lpszMenuName = NULL;
wcex2.lpszClassName = L"SubWindow";
wcex2.hIconSm = 0;
RegisterClassEx(&wcex2);
subWinHwnd = CreateWindowA("SubWindow", nullptr,WS_OVERLAPPEDWINDOW, 0, 0, nWidth, nHeight, NULL, NULL, wcex2.hInstance, 0);
ShowWindow(subWinHwnd, SW_SHOW);
UpdateWindow(subWinHwnd);
MSG msg;
while (GetMessage(&msg, nullptr, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
(3)修改子线程窗口函数
LRESULT CALLBACK SubWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_SUB_MSG:
MessageBoxA(0,"WM_SUB_MSG","子窗体",0);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_LBUTTONDOWN:
MessageBoxA(0,"左键消息","子窗体",0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
(4)修改主窗口的窗口函数
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_LBUTTONDOWN:
{
std::thread t(CreateWndInThread, 960, 480);
t.detach();
}
break;
case WM_RBUTTONDOWN:
{
SendMessage(subWinHwnd,WM_SUB_MSG,0,0);
//PostMessage(subWinHwnd,WM_SUB_MSG,0,0);
MessageBoxA(0,"右键消息","主窗体",0);
}
break;
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// 分析菜单选择:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: 在此添加任意绘图代码...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
(5)运行程序
发现使用SendMessage(subWinHwnd,WM_SUB_MSG,0,0) ,
MessageBoxA(0,"右键消息","主窗体",0) 对话框在 MessageBoxA(0,"WM_SUB_MSG","子窗体",0) 后面出现
使用PostMessage(subWinHwnd,WM_SUB_MSG,0,0)
MessageBoxA(0,"右键消息","主窗体",0) 对话框在MessageBoxA(0,"WM_SUB_MSG","子窗体",0) 前面出现
(6)完整代码链接:https://www.aliyundrive.com/s/UtrYB42wyi3
总结:
PostMessage会将消息压入窗口所在线程的消息队列,然后立即返回,非阻塞
SendMessage则不经过消息队列,SendMessage可认为是直接调用了该窗口的窗口过程,阻塞
最新文章
- CM给hive添加自定义jar包
- Javascript高级程序设计
- ZOJ 3209 Treasure Map (Dancing Links)
- ios 说一说UINavigationController 的堆栈
- java中时间差计算
- webapi Task
- 无状态会话bean(3)---远程业务接口(没有排版)
- 10个漂亮的jQuery日历插件下载【转载】
- bzoj1798 [Ahoi2009]维护序列
- OpenID Connect + OAuth2.0
- [struts2学习笔记] 第三节 创建struts 2 HelloWorld所需的六个步骤
- Spring开发环境搭建教程
- css-不固定宽高定位
- C#从http上拿返回JSON数据
- JDBC遇到向ORACLE数据库表执行插入操作时,报错“列在此处不允许”
- java学习笔记37(sql工具类:JDBCUtils)
- python 操作系统模块 -- OS
- bool类型为什么可以当做int
- js 取一个对象的长度,取出来的是undefined,自己写的一个计算长度的函数解决了。
- beeline 连接hive