繁体   English   中英

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转换; 根据是通过RegisterWindowW还是RegisterWindowA ,窗口是“ Unicode”或“ ANSI”,而取决于是通过SendMessageW / PostMessageW / ...或SendMessageA /来发送,消息是“ Unicode”或“ ANSI” PostMessageA / ....如果两者不匹配,系统将适当地转换消息。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM