WM_TIMER在特定条件下丢失

时间:2017-06-05 18:49:29

标签: c winapi

#include <windows.h>
#include <stdio.h>

class tWnd {
private:
    static LRESULT CALLBACK Disp_test_WndProc(
        HWND hwnd,        // handle to window
        UINT uMsg,        // message identifier
        WPARAM wParam,    // first message parameter
        LPARAM lParam)    // second message parameter
    {
        switch (uMsg) 
        {
            case WM_TIMER:{
                printf("timer\n");

                return 0;
            }

            case WM_PAINT: 
                // Paint the window's client area. 
                return 0; 

            case WM_DESTROY: 
                return 0; 

            case WM_HOTKEY:{

            } return 0;
            // 
            // Process other messages. 
            // 
            default: 
                return DefWindowProc(hwnd, uMsg, wParam, lParam); 
        } 
        return 0; 
    }

public:     
    tWnd() {

            WNDCLASSA wc;
            wc.style = CS_HREDRAW | CS_VREDRAW; 
            wc.lpfnWndProc = (WNDPROC) Disp_test_WndProc; 
            wc.cbClsExtra = 0; 
            wc.cbWndExtra = 0; 
            wc.hInstance = GetModuleHandle(NULL); 
            wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); 
            wc.hCursor = LoadCursor(NULL, IDC_ARROW); 
            wc.hbrBackground = (HBRUSH) NULL; 
            wc.lpszMenuName =  ""; 
            wc.lpszClassName = "Test"; 

            if (!RegisterClass(&wc)) 
               return; //cannot register window class



        HWND testingWindow = CreateWindowEx(WS_EX_TOPMOST,"Test","topmost",WS_VISIBLE,0,0,200,200,0,0,0,0);

        SetTimer(testingWindow,101,500,(TIMERPROC)NULL);

        MSG recent;
        BOOL result;
        while((result=GetMessage(&recent,testingWindow,0,0))&&result!=-1) { //bool can be -1 in MS world
            if(recent.message==WM_USER+1) break;
            TranslateMessage(&recent);
            DispatchMessage(&recent);
        }
    }
};

int main(int argc, char **argv)
{
    tWnd();
    return 0;
}

此代码永远不会收到WM_TIMER消息。

#include <windows.h>
#include <stdio.h>

class tWnd {
private:
    static LRESULT CALLBACK Disp_test_WndProc(
        HWND hwnd,        // handle to window
        UINT uMsg,        // message identifier
        WPARAM wParam,    // first message parameter
        LPARAM lParam)    // second message parameter
    {
        switch (uMsg) 
        {
            case WM_TIMER:{
                printf("timer\n");

                return 0;
            }

            case WM_DESTROY: 
                return 0; 

            case WM_HOTKEY:{

            } return 0;
            // 
            // Process other messages. 
            // 
            default: 
                return DefWindowProc(hwnd, uMsg, wParam, lParam); 
        } 
        return 0; 
    }

public:     
    tWnd() {

            WNDCLASSA wc;
            wc.style = CS_HREDRAW | CS_VREDRAW; 
            wc.lpfnWndProc = (WNDPROC) Disp_test_WndProc; 
            wc.cbClsExtra = 0; 
            wc.cbWndExtra = 0; 
            wc.hInstance = GetModuleHandle(NULL); 
            wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); 
            wc.hCursor = LoadCursor(NULL, IDC_ARROW); 
            wc.hbrBackground = (HBRUSH) NULL; 
            wc.lpszMenuName =  ""; 
            wc.lpszClassName = "Test"; 

            if (!RegisterClass(&wc)) 
               return; //cannot register window class



        HWND testingWindow = CreateWindowEx(WS_EX_TOPMOST,"Test","topmost",WS_VISIBLE,0,0,200,200,0,0,0,0);

        SetTimer(testingWindow,101,500,(TIMERPROC)NULL);

        MSG recent;
        BOOL result;
        while((result=GetMessage(&recent,testingWindow,0,0))&&result!=-1) { //bool can be -1 in MS world
            if(recent.message==WM_USER+1) break;
            TranslateMessage(&recent);
            DispatchMessage(&recent);
        }
    }
};

int main(int argc, char **argv)
{
    tWnd();
    return 0;
}

此代码可以很好地获取WM_TIMER消息。

两者之间的唯一区别是WM_PAINT消息在第二个变体中是默认处理的。为什么要处理WM_PAINT会阻止程序接收WM_TIMER消息?我该如何解决这个问题?

如果重要的话,我正在使用MingW w64(GCC 5.3.0)。

1 个答案:

答案 0 :(得分:5)

当窗口的无效区域为非空时,窗口会收到import scala.collection.mutable val jac_index: (mutable.WrappedArray[String], mutable.WrappedArray[String]) => Float = (Sq1, Sq2) => { /* same implementation */ } 消息。这在ValidateRect()的文档中被提及:

  

系统会继续生成WM_PAINT条消息,直到验证当前更新区域为止。

标准WM_PAINT处理程序验证无效区域(例如,通过调用BeginPaint()),默认实现是这样做的。简单地返回WM_PAINT将不会验证窗口,并且它会继续接收0条消息。

WM_PAINT条消息的优先级低于WM_TIMER条消息。您的窗口过程永远不会看到计时器消息,因为它一直忙于忽略绘制消息。这在WM_TIMER的文档中被提及:

  

WM_PAINT消息是低优先级消息。仅当线程的消息队列中没有其他更高优先级的消息时,GetMessagePeekMessage函数才会发布此消息。