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. 《Django 3 Web应用开发从零开始学(视频教学版)》源码课件教学视频免费下载

    #好书推荐##好书奇遇季#<Django 3 Web应用开发从零开始学(视频教学版)>,配书资源文后提供了下载二维码.京东当当天猫都有发售. https://item.jd.com/133 ...

  2. notepad++ 编写html代码快捷键切换到浏览器查看

    1.右键chrome属性,查看目标C:\Users\duanx\AppData\Local\Google\Chrome\Application\chrome.exe 2.然后notepad运行,输入如 ...

  3. SAP 自建事务码

    自建事务码的 事务码 se93 一般来说开发人员会遇到,开发了报表已经一些功能,不会让业务人员通过se38来进行使用,一般会新建一个事务码让业务人员在t-code中的使用 配置对应的程序即可

  4. pyhon&QT编译

    1.编译qrcpyrcc5 -o ico_rc.py ./ico/ico.qrc.qrc文件格式<RCC> <qresource prefix="/"> & ...

  5. 从URL中获取参数

    1.跳转测试页面  获取的url上的参数    <!doctype html> <html lang="en"> <head>     < ...

  6. javaSE-验证码生成

    一.使用Math类的radom() 方法 //生成验证码 String verifcationCode = ""; for (int i = 0; i <= 5; i++) ...

  7. etcd 基于ubuntu 20.04 部署集群

    Etcd是Kubernetes集群中的一个十分重要的组件,用于保存集群所有的网络配置和对象的状态信息,K8S中所有持久化的状态信息都是以Key-Value的形式存储在etcd中,提供分布式协调服务.之 ...

  8. Delphi中类的VMT

    TObject是所有对象的基本类,DELPHI中的任何对象都是一个指针,这个指针指明该对象在内存中所占据的一块空间!     对象空间的头4个字节是指向该对象类的虚方法地址表(VMT-Vritual  ...

  9. eggjs中egg-mysql不支持mysql集群,代码修改为支持集群

    说明:暂不支持egg-mysql动态数据源,用到动态数据源请自行修改.欢迎各位大佬指导... 集群配置: exports.mysql = { // 单数据库信息配置 client: { db1: { ...

  10. opencv基本函数详解笔记

    一.读取保存图片 Mat scrImage = imread("1.jpg"); //显示图像 imshow("原图", scrImage); //窗口等待 w ...