首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >WndProc调用机制(WinAPI)

WndProc调用机制(WinAPI)
EN

Stack Overflow用户
提问于 2016-02-07 01:26:18
回答 2查看 7.3K关注 0票数 4

我试图了解windows应用程序是如何工作的。

有一个WndProc函数,其中发生消息处理。

代码语言:javascript
复制
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)函数调用:

代码语言:javascript
复制
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。这些消息通知窗口它已被激活,键盘输入被定向到该窗口,并且鼠标光标已移动到窗口的边界内。当应用程序调用某些系统功能时,也会产生非排队消息。例如,系统在应用程序使用WM_WINDOWPOSCHANGED函数移动窗口后发送SetWindowPos消息。

结果表明,非排队消息仅在窗口初始化时出现,而所有后续的非队列消息只能是在我的程序中调用WinAPI函数的结果。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-02-07 01:32:24

没有什么特别神奇的,如果SendMessage是从创建窗口的同一个线程调用的,那么窗口过程将由SendMessage直接调用,否则请求将排队,SendMessage()等待消息循环处理请求。这是记录在案的行为:

函数

如果指定的窗口是由调用线程创建的,则将立即作为子例程调用窗口过程。如果指定的窗口是由不同的线程创建的,则系统切换到该线程并调用适当的窗口过程。只有当接收线程执行消息检索代码时,才会处理在线程之间发送的消息。发送线程将被阻塞,直到接收线程处理该消息。

函数

分发传入的发送消息,检查线程消息队列中的已发布消息,并检索消息(如果存在的话)。 ..。 在此调用期间,系统传递挂起的、非排队的消息,即使用SendMessage、SendMessageCallback、SendMessageTimeout或SendNotifyMessage函数将消息发送到调用线程拥有的窗口。然后检索与指定筛选器匹配的第一个排队消息。系统还可以处理内部事件。

函数

从调用线程的消息队列中检索消息。函数分发传入的发送消息,直到发布的消息可供检索为止。 ..。 在此调用期间,系统传递挂起的、非排队的消息,即使用SendMessage、SendMessageCallback、SendMessageTimeout或SendNotifyMessage函数将消息发送到调用线程拥有的窗口。然后检索与指定筛选器匹配的第一个排队消息。系统还可以处理内部事件。

唯一的魔力是:

  • 有些消息不是“真正的”排队,而是由GetMessage合成的,如果没有更好的方法(→重绘、鼠标移动消息、计时器等);
  • 消息分派处理系统“知道”的消息的Unicode转换;窗口是"Unicode“或"ANSI”,取决于它是通过RegisterWindowW还是RegisterWindowA注册的,而发送的消息是"Unicode“或"ANSI”,这取决于它是通过SendMessageW/PostMessageW/发送的.或者SendMessageA/PostMessageA/..。如果两者不匹配,系统将适当地转换消息。

不涉及并行性,窗口过程的好处是它们总是从创建窗口的线程调用。

票数 10
EN

Stack Overflow用户

发布于 2021-08-17 09:12:54

除了意大利马泰奥的回答之外,我想指出的是,SendMessage 还分发传入的发送消息。正在等待它发送的信息被处理。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35248676

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档