当前位置:网站首页>Analysis of GetMessage underlying mechanism
Analysis of GetMessage underlying mechanism
2022-07-01 19:35:00 【Little bug】
GUI The message queue of thread is actually divided into seven sub message queues ,
One of the sub message queues is dedicated to storing sendmessage Function to send messages across threads
GetMessage The inner circle will first judge sendMessageListHead Whether there are messages in the sub message queue ,
If so, call KeUserModeCallBack Return to the third ring and call the window procedure function of the corresponding window to process the message ,
All etc. sendMessageListHead In the sub message queue
After the message is processed , Will get messages from other queues in turn ,
At this time, if you get the message, you will jump out of the outer loop GetMessage The function returns ;
And pass the obtained message to dispatchMessage Function processing ;
If you don't get the message, you will keep repeating =>GetMessage Blocking effect
Pay attention to handling in the above process sendMessageListHead Messages in the sub queue ,
Is in GetMessage Function internal direct call KeUserModeCallBack Finally, it calls the window procedure function to process ;
For other messages, just get and return ;
Why do you say sendMessageListHead What's stored is sendmessage The message passed by the function across threads ,
because sendMessage Only when the message is delivered across threads can it go to the message queue ,
If it's the same process sendMessage Directly call the corresponding window procedure function ,
The message will not be put into the message queue, that is, the message will not be put into sendMessageListHead Sub message queue
// WinMessage.cpp : Define the entry point for the application .
//
#include "framework.h"
#include "WinMessage.h"
#define MAX_LOADSTRING 100
// Global variables :
HINSTANCE hInst; // The current instance
WCHAR szTitle[MAX_LOADSTRING]; // Title bar text
WCHAR szWindowClass[MAX_LOADSTRING]; // Main window class name
HWND g_hwnd;
// Forward declaration of functions contained in this code module :
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Put the code here .
// Initialize global string
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_WINMESSAGE, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization :
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WINMESSAGE));
MSG msg;
SendMessage(g_hwnd, WM_LBUTTONDOWN, 0, 0);// If sendMessage No messages are sent across threads Even if the entire message cycle is commented out , You can still call window procedure functions => At this time, the message does not enter the message queue for storage
// Main message loop :
/* while (GetMessage(&msg, nullptr, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } }*/
return 0;
}
//
// function : MyRegisterClass()
//
// The goal is : Register window class .
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WINMESSAGE));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_WINMESSAGE);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
//
// function : InitInstance(HINSTANCE, int)
//
// The goal is : Save the instance handle and create the main window
//
// notes :
//
// In this function , We save the instance handle in the global variable and
// Create and display the main program window .
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Store instance handles in global variables
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
g_hwnd = hWnd;
return TRUE;
}
//
// function : WndProc(HWND, UINT, WPARAM, LPARAM)
//
// The goal is : Processing messages from the main window .
//
// WM_COMMAND - Handle the application menu
// WM_PAINT - Draw the main window
// WM_DESTROY - Send an exit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// Analysis menu selection :
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:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: Add here to use hdc Any drawing code for ...
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_LBUTTONDOWN:// Still implemented
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// “ About ” Box message handler .
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
边栏推荐
- ES6中的代理proxy
- web开发常用的开源框架的开源协议整理
- Dlib+opencv library for fatigue detection
- OpenCV视频质量诊断----视频遮挡诊断
- 宝,运维100+服务器很头疼怎么办?用行云管家!
- The difference between indexof and includes
- Ubuntu14 install MySQL and configure root account local and remote access
- Boost the development of digital economy and consolidate the base of digital talents - the digital talent competition was successfully held in Kunming
- 【英语语法】Unit1 冠词、名词、代词和数词
- English语法_形容词/副词3级 -注意事项
猜你喜欢
测试自学人必看:软件测试如何找测试项目?
精耕渠道共謀發展 福昕攜手偉仕佳傑開展新產品培訓大會
ubuntu14安装MySQL并配置root账户本地与远程访问
Solidity - 算术运算的截断模式(unchecked)与检查模式(checked)- 0.8.0新特性
为什么一定要从DevOps走向BizDevOps?
What must be done in graduation season before going to Shanhai
商业智能BI开发和报表开发有什么本质区别?
Flutter 实战-快速实现音视频通话应用
EasyGBS网络不稳定情况下重复请求视频拉流问题的优化
wireshark报文分析tcp,ftp
随机推荐
OpenCV视频质量检测--清晰度检测
EasyGBS网络不稳定情况下重复请求视频拉流问题的优化
【英语语法】Unit1 冠词、名词、代词和数词
[go ~ 0 to 1] day 5 July 1 type alias, custom type, interface, package and initialization function
Solution and summary of Nacos startup failure
Chinese and English instructions human soluble advanced glycation end products receptor (sRAGE) ELISA Kit
音频编解码基础知识
sql查询去重统计的方法总结
Introduction and installation of crunch, and making password dictionary with crunch
MFC中如何重绘CListCtrl的表头
采集抖音视频
118. 杨辉三角
求各种极限的方法
[6.24-7.1] review of wonderful technical blog posts in the writing community
Reading the paper [learning to discretely compose reasoning module networks for video captioning]
H264 encoding profile & level control
事务隔离级别 gap锁 死锁
赋能「新型中国企业」,SAP Process Automation 落地中国
A brief understanding of white box encryption technology
OpenCV视频质量诊断----视频遮挡诊断