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

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. windows下C#读文件遇到一个路径的天坑

    在win下面准备了一个文件,右键属性然后"安全"复制完整的文件路径, 放到C#代码(vs中编写)中来读取,竟然死活异常: System.IO.IOException HResult ...

  2. Codeforces Round #766 (Div. 2) - D. Not Adding

    GCD + 调和级数 Problem - 1627D - Codeforces 题意 有 \(n\;(1<=n<=10^6)\) 个互不相同的数 \(a[i]\;(1<=a[i]&l ...

  3. 给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案

    var threeSumClosest = function(nums, target) { let ans = nums[0] + nums[1] + nums[2]; const len = nu ...

  4. Linux7重置root管理员密码

    1.先确定是否为rhel 7系统(别的系统我没有试过,请慎重尝试) cat /etc/redhat-release 查看Linux的操作系统 2.按键盘e键进入内核编辑界面 3.找到linux16这行 ...

  5. Android中操作 SDCard文件

    1 import android.content.Context; 2 import android.graphics.Bitmap; 3 import android.graphics.Bitmap ...

  6. el-dialog 嵌套子组件数据不刷新

    <!-- 展示通道测量值 -->     <el-dialog :title="analogTitle" :visible.sync="analogOp ...

  7. 学习canvas的vscode提示问题

    在代码中加入/** @type {HTMLCanvasElement} */ 即可 1 <script> 2 /** @type {HTMLCanvasElement} */ 3 let ...

  8. mysql5.7主从多线程同步

    数据库复制的主要性能问题就是数据延时 为了优化复制性能,Mysql 5.6 引入了 "多线程复制" 这个新功能 但 5.6 中的每个线程只能处理一个数据库,所以如果只有一个数据库, ...

  9. 【Java】dto转json

    <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifac ...

  10. Mysql--查询"01"课程比"02"课程成绩高的学生的信息及课程分数

    今天在写Mysql代码作业时,写到这个题,感觉值得分享!!!!!!! 查询"01"课程比"02"课程成绩高的学生的信息及课程分数 分析如下: 首先先查询&quo ...