2017-06-05 28 views
-1
#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消息。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)。

+0

请在问题中发布代码,而不是在现场。 –

+0

@MikeNakis done –

+0

我不知道为什么会发生这种情况,但是如果Windows检测到你是a)不允许默认处理WM_PAINT消息,并且b)不自己做任何实际的绘画,我不会感到惊讶,所以它认为你的应用程序可能会忙于某些事情,所以最好不要用计时器消息来打扰它。无论如何,这是非常不规范的,我不会太担心。 –

回答

5

当窗口的无效区域非空时,窗口收到WM_PAINT消息。这是在文档中叫出来ValidateRect()

系统继续,直到当前的更新区域进行验证,以产生WM_PAINT消息。

标准WM_PAINT处理程序验证无效区域(例如,通过调用BeginPaint()),默认实现会执行此操作。只需返回0就不会验证该窗口,并且它将继续收到WM_PAINT消息。

WM_TIMER消息比WM_PAINT消息的优先级低。您的窗口过程从不会看到定时器消息,因为它始终忙于忽略绘制消息。这是在文档中叫出来WM_TIMER

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

+0

有效的WM_PAINT处理应该具有哪些内容? https://msdn.microsoft.com/en-us/library/windows/desktop/dd145194%28v=vs.85%29.aspx - 这个? –

+2

@EuriPinhollow:它需要验证无效区域。它通常通过调用'BeginPaint'来完成,然后绘制无效部分。如果你没有任何绘画,你也可以调用'ValidateRect'。 – IInspectable