WndProc调用机制(WinAPI)
WndProc calling mechanism (WinAPI)
我试图了解Windows应用程序的工作原理。
有一个 WndProc 函数,其中发生消息处理。
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_KEYDOWN:
if (wParam == VK_ESCAPE) {
if (MessageBox(0, L"Are you sure?", L"Exit?", MB_YESNO | MB_ICONQUESTION) == IDYES)
//Release the windows allocated memory
DestroyWindow(hwnd);
}
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
可以在两种情况下调用此函数:
A( 由 DispatchMessage(&msg( 函数在消息循环周期中调用:
while (true){
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
B( 在收到非排队消息时由 Windows 调用。
这是如何工作的?Windows如何在不使用并行性的情况下立即调用WndProc函数?您能否详细描述函数调用的机制?
MSDN 官方文档说:
原来,非排队消息未排队的消息将立即发送到目标窗口过程,绕过系统消息队列和线程消息队列。系统通常发送非排队消息,以通知影响它的事件的窗口。例如,当用户激活新的应用程序窗口时,系统会向该窗口发送一系列消息,包括WM_ACTIVATE、WM_SETFOCUS和WM_SETCURSOR。这些消息通知窗口它已被激活,键盘输入正在定向到窗口,并且鼠标光标已在窗口边框内移动。当应用程序调用某些系统函数时,也可能导致非排队消息。例如,系统在使用 SetWindowPos 函数移动窗口后发送WM_WINDOWPOSCHANGED消息。
只在窗口初始化时出现,所有后续的非排队消息只能是在我的程序中调用 WinAPI 函数的结果?
没有什么特别神奇的,如果从创建窗口的同一线程调用SendMessage
,则窗口过程由SendMessage
直接调用,否则请求将排队,SendMessage()
等待消息循环处理请求。这是记录的行为:
SendMessage
功能
如果指定的窗口是由调用线程创建的,则窗口过程将立即作为子例程调用。如果指定的窗口是由其他线程创建的,则系统会切换到该线程并调用相应的窗口过程。仅当接收线程执行消息检索代码时,才会处理线程之间发送的消息。发送线程将被阻止,直到接收线程处理消息。
PeekMessage
功能
调度传入的已发送消息,检查线程消息队列中是否有已发布的消息,并检索该消息(如果存在(。
。
在此调用期间,系统传递挂起的非排队消息,即使用 SendMessage、SendMessageCallback、SendMessageTimeout 或 SendNotifyMessage 函数发送到调用线程拥有的窗口的消息。然后检索与指定筛选器匹配的第一个排队消息。系统还可以处理内部事件。
GetMessage
功能
从调用线程的消息队列中检索消息。该函数调度传入的已发送消息,直到已发布的消息可供检索。
。
在此调用期间,系统传递挂起的非排队消息,即使用 SendMessage、SendMessageCallback、SendMessageTimeout 或 SendNotifyMessage 函数发送到调用线程拥有的窗口的消息。然后检索与指定筛选器匹配的第一个排队消息。系统还可以处理内部事件。
唯一的魔力是:
- 有些消息不是"真正"排队的,而是由
GetMessage
合成的,如果没有更好的事情要做(→重绘,鼠标移动消息,计时器等(; - 消息调度处理系统"知道"的消息的Unicode转换;一个窗口是"Unicode"还是"ANSI",这取决于它是通过
RegisterWindowW
还是RegisterWindowA
注册的,发送的消息是"Unicode"还是"ANSI",这取决于它是通过SendMessageW
/PostMessageW
/发送的。或SendMessageA
/PostMessageA
/....如果两者不匹配,系统会相应地转换消息。
不涉及并行性,窗口过程的好处是它们始终从创建窗口的线程调用。
除了Matteo Italia的回答之外,我想指出的是,SendMessage
在等待发送的消息被处理时也会调度传入的已发送消息。
- WinAPI挂钩鼠标
- 将执行、作业和WinAPI相乘
- 如何在桌面C++上使用 WinApi 画线
- WINAPI 注册应用程序重新启动时不清除打开的套接字
- Winapi:屏幕截图未显示在窗口中
- WinAPI 在单击第一个对话框上的按钮控件并销毁第一个对话框后创建第二个对话框
- Qt with WinAPI MouseProc
- 如何在"SUBSYSTEM:WINDOWS"下显示并输出到Windows(C++ WinApi)上的
- WinAPI 无法创建按钮
- 将 Win32/WinAPI 应用程序移植到 wxWidgets
- WinAPI 检查窗口是否具有常规标题栏
- 使用共享指针时,从共享指针本身释放内存的机制是什么
- 如何使用带有矢量的 winapi 读取进程内存从另一个进程读取缓冲区?
- 将Qt集成到现有的VS项目中以取代WinAPI
- 为什么 boost::comb 对结构化绑定的支持缺少结构化绑定机制对 boost::tuples::cons 的适应?
- __stdcall - WINAPI vs STDMETHODCALLTYPE vs APIENTRY
- 如何将'this'指针传递给C++ WinAPI 线程?
- 了解使用堆栈实现队列的递归调用机制
- WndProc调用机制(WinAPI)
- 如何在WinAPI中创建一对多的等待机制