1.子线程中建立一个窗口

为了在后面比较这两个函数,先使用win32 windows程序中建立子线程,在子线程中建立一个窗口。

(1)新建一个 win32 windows应用程序

(2)定义子窗口的窗口响应函数

  1. LRESULT CALLBACK SubWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  2. {
  3. switch (message)
  4. {
  5. case WM_DESTROY:
  6. PostQuitMessage(0);
  7. break;
  8. case WM_LBUTTONDOWN:
  9. MessageBoxA(0,"","SubWndProc",0);
  10. break;
  11. default:
  12. return DefWindowProc(hWnd, message, wParam, lParam);
  13. }
  14. }

(3)定义子线程窗口函数

  1. void CreateWndInThread(int nWidth, int nHeight)
  2. {
  3. WNDCLASSEX wcex2;
  4. wcex2.cbSize = sizeof(WNDCLASSEX);
  5. wcex2.style = CS_HREDRAW | CS_VREDRAW;
  6. wcex2.lpfnWndProc = SubWndProc;
  7. wcex2.cbClsExtra = 0;
  8. wcex2.cbWndExtra = 0;
  9. wcex2.hInstance = GetModuleHandle(nullptr);
  10. wcex2.hIcon = 0;
  11. wcex2.hCursor = LoadCursor(nullptr, IDC_ARROW);
  12. wcex2.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  13. wcex2.lpszMenuName = NULL;
  14. wcex2.lpszClassName = L"SubWindow";
  15. wcex2.hIconSm = 0;
  16. RegisterClassEx(&wcex2);
  17. HWND g_hWnd = CreateWindowA("SubWindow", nullptr,WS_OVERLAPPEDWINDOW, 0, 0, nWidth, nHeight, NULL, NULL, wcex2.hInstance, 0);
  18. ShowWindow(g_hWnd, SW_SHOW);
  19. UpdateWindow(g_hWnd);
  20. MSG msg;
  21. while (GetMessage(&msg, nullptr, 0, 0))
  22. {
  23. TranslateMessage(&msg);
  24. DispatchMessage(&msg);
  25. }
  26. }

(4)处理主线程的 WM_LBUTTONDOWN 消息

在里面开启一个子线程,调用 CreateWndInThread

  1. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  2. {
  3. int wmId, wmEvent;
  4. PAINTSTRUCT ps;
  5. HDC hdc;
  6. switch (message)
  7. {
  8.  
  9. case WM_LBUTTONDOWN:
  10. {
  11. std::thread t(CreateWndInThread, 960, 480);
  12. t.detach();
  13. }
  14. break;
  15. //省略其他消息
  16. default:
  17. return DefWindowProc(hWnd, message, wParam, lParam);
  18. }
  19. break;
  20. default:
  21. return DefWindowProc(hWnd, message, wParam, lParam);
  22. }
  23. return 0;
  24. }

(5)运行程序

在主窗口上鼠标左键点击,会创建一个子窗口,

然后在子窗口上鼠标左键点击,会弹出一个MessageBox。

可以发现两个窗口的消息处理互不影响。

2.PostMessage和SendMessage

PostMessage会将消息压入窗口所在线程的消息队列,然后立即返回,非阻塞

SendMessage则不经过消息队列,SendMessage可认为是直接调用了该窗口的窗口过程,阻塞

将上面的项目做如下修改:

(1)定义一个全局遍历来存储子窗体的句柄,定义子窗体自定义消息

  1. #define WM_SUB_MSG (WM_USER+1)
  2. HWND subWinHwnd;//子窗口

(2)修改子窗口的窗口响应函数

  1. void CreateWndInThread(int nWidth, int nHeight)
  2. {
  3. WNDCLASSEX wcex2;
  4. wcex2.cbSize = sizeof(WNDCLASSEX);
  5. wcex2.style = CS_HREDRAW | CS_VREDRAW;
  6. wcex2.lpfnWndProc = SubWndProc;
  7. wcex2.cbClsExtra = 0;
  8. wcex2.cbWndExtra = 0;
  9. wcex2.hInstance = GetModuleHandle(nullptr);
  10. wcex2.hIcon = 0;
  11. wcex2.hCursor = LoadCursor(nullptr, IDC_ARROW);
  12. wcex2.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  13. wcex2.lpszMenuName = NULL;
  14. wcex2.lpszClassName = L"SubWindow";
  15. wcex2.hIconSm = 0;
  16. RegisterClassEx(&wcex2);
  17. subWinHwnd = CreateWindowA("SubWindow", nullptr,WS_OVERLAPPEDWINDOW, 0, 0, nWidth, nHeight, NULL, NULL, wcex2.hInstance, 0);
  18. ShowWindow(subWinHwnd, SW_SHOW);
  19. UpdateWindow(subWinHwnd);
  20. MSG msg;
  21. while (GetMessage(&msg, nullptr, 0, 0))
  22. {
  23. TranslateMessage(&msg);
  24. DispatchMessage(&msg);
  25. }
  26. }

(3)修改子线程窗口函数

  1. LRESULT CALLBACK SubWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  2. {
  3. switch (message)
  4. {
  5. case WM_SUB_MSG:
  6. MessageBoxA(0,"WM_SUB_MSG","子窗体",0);
  7. break;
  8. case WM_DESTROY:
  9. PostQuitMessage(0);
  10. break;
  11. case WM_LBUTTONDOWN:
  12. MessageBoxA(0,"左键消息","子窗体",0);
  13. break;
  14. default:
  15. return DefWindowProc(hWnd, message, wParam, lParam);
  16. }
  17. }

(4)修改主窗口的窗口函数

  1. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  2. {
  3. int wmId, wmEvent;
  4. PAINTSTRUCT ps;
  5. HDC hdc;
  6. switch (message)
  7. {
  8. case WM_LBUTTONDOWN:
  9. {
  10. std::thread t(CreateWndInThread, 960, 480);
  11. t.detach();
  12. }
  13. break;
  14. case WM_RBUTTONDOWN:
  15. {
  16. SendMessage(subWinHwnd,WM_SUB_MSG,0,0);
  17. //PostMessage(subWinHwnd,WM_SUB_MSG,0,0);
  18. MessageBoxA(0,"右键消息","主窗体",0);
  19. }
  20. break;
  21. case WM_COMMAND:
  22. wmId = LOWORD(wParam);
  23. wmEvent = HIWORD(wParam);
  24. // 分析菜单选择:
  25. switch (wmId)
  26. {
  27. case IDM_ABOUT:
  28. DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
  29. break;
  30. case IDM_EXIT:
  31. DestroyWindow(hWnd);
  32. break;
  33. default:
  34. return DefWindowProc(hWnd, message, wParam, lParam);
  35. }
  36. break;
  37. case WM_PAINT:
  38. hdc = BeginPaint(hWnd, &ps);
  39. // TODO: 在此添加任意绘图代码...
  40. EndPaint(hWnd, &ps);
  41. break;
  42. case WM_DESTROY:
  43. PostQuitMessage(0);
  44. break;
  45. default:
  46. return DefWindowProc(hWnd, message, wParam, lParam);
  47. }
  48. return 0;
  49. }

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

windows消息机制_PostMessage和SendMessage的更多相关文章

  1. 收藏:Windows消息机制

    百度百科介绍的windows消息机制也不错:http://baike.baidu.com/view/672379.htm Windows的应用程序一般包含窗口(Window),它主要为用户提供一种可视 ...

  2. 转:Windows消息机制要点

    Windows消息机制要点 1. 窗口过程     每个窗口会有一个称为窗口过程的回调函数(WndProc),它带有四个参数,分别为:窗口句柄(Window Handle),消息ID(Message ...

  3. windows消息机制(转)

    1. 引言Windows 在操作系统平台占有绝对统治地位,基于Windows 的编程和开发越来越广泛.Dos 是过程驱动的,而Windows 是事件驱动的[6],这种差别的存在使得很多Dos 程序员不 ...

  4. 深入理解windows 消息机制

    深入理解Windows消息机制 今天我们来学一学Windows消息机制,我们知道在传统的C语音程序中,当我们需要打开一个文件时,我们可以调用fopen()函数,这个函数最后又会调用操作系统提供的函数以 ...

  5. Windows消息机制

    Windows的消息系统是由3个部分组成的: · 消息队列.Windows能够为所有的应用程序维护一个消息队列.应用程序必须从消息队列中获取消息,然后分派给某个窗口.· 消息循环.通过这个循环机制应用 ...

  6. 我对windows消息机制的理解(参考深入浅出MFC,欢迎批评指正!!)

    以消息为基础,以事件驱动之 程序的进行依靠外部消息来驱动,即:程序不断等待任何可能的输入,然后做判断,然后再做适当的处理. 消息输入:操作系统捕获,以消息形式进入程序.(操作系统通过其USERS模块中 ...

  7. <Win32_1>深入浅出windows消息机制[转自crocodile_]

    上学期学习了Java ,感觉Java写一个窗口真心简单,很易上手,也就难怪很多开发人员选择Java作为自己的开发编程语言.但是由于自身对windows的热爱,让我觉得c.c++语言才是我亲睐的编程语言 ...

  8. 深入Delphi -- Windows 消息机制

    http://www.txsz.net/xs/delphi/3/Windows%20%E6%B6%88%E6%81%AF%E6%9C%BA%E5%88%B6.htm Windows 消息机制 by m ...

  9. windows消息机制框架原理【简单版本】

    windows消息机制框架原理 结合两张图理解 窗口和窗口类 Windows UI 应用程序 (e) 具有一个主线程 (g).一个或多个窗口 (a) 和一个或多个子线程 (k) [工作线程或 UI 线 ...

  10. Windows消息机制详解

    消息是指什么?      消息系统对于一个win32程序来说十分重要,它是一个程序运行的动力源泉.一个消息,是系统定义的一个32位的值,他唯一的定义了一个事件,向 Windows发出一个通知,告诉应用 ...

随机推荐

  1. managing projects with GNU make pdf

    读 c++编程思想的时候作者推荐的关于makefile的书,大家随意抱走. 链接:https://pan.baidu.com/s/1k0qg9iA3V25C2yJnOi9WfQ 提取码:5vx1

  2. SVNKit操作SVN

    系统集成SVN(SVNKit操作SVN) 网址:https://svnkit.com/documentation.html 文档:https://svnkit.com/javadoc/index.ht ...

  3. cuda 11.8

    wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-keyring_1.0-1_a ...

  4. 时间处理及interval函数运用

    MySql时间操作1.interval的说明1.1.当函数使用时,即interval(),为比较函数,如:interval(10,1,3,5,7); 结果4:原理:10为被比较数,后面1,3,5,7为 ...

  5. GIT 上传文件出错:fatal: Could not read from remote repository. 解决方案

    问题 git push -u origin master 执行后报错 fatal: Could not read from remote repository.  解决方案 1. git执行 git ...

  6. VUE2.0 脚手架搭建项目,如何配置本地IP地址访问项目,详解

    1.首先找到config文件夹目录下的 index.js文件 // Various Dev Server settings //host: 'localhost' //将localhost进行替换成 ...

  7. 肖sir__面试第十天课程__模拟面试讲解

    一.面对面模拟面试1.打印好简历2.带好手机,录制自己回答的问题,总结,反思(内部),关闭手机和闹钟(外部)3.有笔试题,可以拍照发群里4.可以携带耳塞(适合女生)5.语速流程6.礼貌用语(面试官好, ...

  8. jmeter非GUI模式压测并生成测试报告

    关于jmeter非GUI模式压测并生成测试报告 1.脚本调通后,在DOS命令栏进入脚本存在的位置 如果不想通过DOS进入脚本路径,则可以直接指定执行路径,命令如下: JMeter默认去当前目录寻找脚本 ...

  9. python_列表(list)

    列表用中括号表示,列表中的数据可以存储不同类型的数据,在实际开发中,列表中都是定义相同类型数据,可以对列表中的数据用相同的方法进行处理. 1, 通过index获取到对应的值. num_list = [ ...

  10. 基于Python的简单读卡上位机界面

    使用到的模块,pyserial  pyqt5  pymysql (我先是实现在命令行下通过串口进行对板子硬件的控制,比如Led ,beep等,在实现检测卡(是否选卡成功),连接卡(验证哪一个扇区),读 ...