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可认为是直接调用了该窗口的窗口过程,阻塞

最新文章

  1. CM给hive添加自定义jar包
  2. Javascript高级程序设计
  3. ZOJ 3209 Treasure Map (Dancing Links)
  4. ios 说一说UINavigationController 的堆栈
  5. java中时间差计算
  6. webapi Task
  7. 无状态会话bean(3)---远程业务接口(没有排版)
  8. 10个漂亮的jQuery日历插件下载【转载】
  9. bzoj1798 [Ahoi2009]维护序列
  10. OpenID Connect + OAuth2.0
  11. [struts2学习笔记] 第三节 创建struts 2 HelloWorld所需的六个步骤
  12. Spring开发环境搭建教程
  13. css-不固定宽高定位
  14. C#从http上拿返回JSON数据
  15. JDBC遇到向ORACLE数据库表执行插入操作时,报错“列在此处不允许”
  16. java学习笔记37(sql工具类:JDBCUtils)
  17. python 操作系统模块 -- OS
  18. bool类型为什么可以当做int
  19. js 取一个对象的长度,取出来的是undefined,自己写的一个计算长度的函数解决了。
  20. beeline 连接hive

热门文章

  1. qgis中的时间格式化函数
  2. lxml库和BeautifulSoup库常用点小结
  3. Vulnhub 靶场 BEELZEBUB: 1
  4. 上传媒体文件--添加显示进度条 layui的upload控件
  5. Jmeter(三十九) - 从入门到精通进阶篇 - Jmeter配置文件的刨根问底 - 上篇(详解教程)
  6. 19c 滚动升级
  7. 全新BPMN常用图形标识一览表
  8. Text文件颜色渐变
  9. Token过期导致页面多个请求报错提示多次
  10. Jmeter安装及环境配置