zoukankan      html  css  js  c++  java
  • atlwin中不停发WM_PAINT消息原因分析

    这里我们基于atlwin定义的窗口类SampleWindow继承自CWindowImpl(定义见atlwin.h),并注册了WM_PAINT消息处理函数OnPaint,注意,我们在OnPaint函数中并没有直接处理WM_PAINT消息,而是直接返回了FALSE

     1 class SampleWindow : public CWindowImpl<SampleWindow> 2 {
     3 public:
     4     SampleWindow():
     5     
     6      
     7       DECLARE_WND_SUPERCLASS(_T("SampleWindow"), NULL)
     8 
     9       BEGIN_MSG_MAP(SampleWindow)
    10          
    11           MESSAGE_HANDLER(WM_PAINT, OnPaint)
    12         
    13       END_MSG_MAP()
    14     
    15         LRESULT OnPaint(UINT msg, WPARAM wparam, LPARAM lparam, BOOL &handled)
    16         {                      
    17             return FALSE;
    18         }
    19 
    20 }

    参考MESSAGE_HANDLER的宏定义就会发现,在执行对应的消息响应函数之前,bHandled默认被赋值为了TRUE(所以通常情况下WM_PAINT消息需要在这里处理),但是参照上述代码,OnPaint函数并未对WM_PAINT消息处理,并且直接返回了FALSE,而MESSAGE_HANDLER默认是返回TRUE的。

    1 #define MESSAGE_HANDLER(msg, func) \
    2     if(uMsg == msg) \
    3     { \
    4         bHandled = TRUE; \
    5         lResult = func(uMsg, wParam, lParam, bHandled); \
    6         if(bHandled) \
    7             return TRUE; \
    8     }

    在代码执行到WindowProc后,pThis->ProcessWindowMessage函数会依次执行上述注册的消息响应函数,在执行到WM_PAINT消息后,bRet为TRUE,导致代码不能够执行lRes = pThis->DefWindowProc(uMsg, wParam, lParam);

    ,而是执行了pThis->m_pCurrentMsg = pOldMsg;,消息处理过程函数WindowProc返回结果lRes为0,导致系统不停的发送WM_PAINT消息(导致消息不停发送的原因并不是WindowProc返回0,是WM_PAINT消息未得到处理),造成死循环

     1 template <class TBase, class TWinTraits>
     2 LRESULT CALLBACK CWindowImplBaseT< TBase, TWinTraits >::WindowProc(
     3     _In_ HWND hWnd,
     4     _In_ UINT uMsg,
     5     _In_ WPARAM wParam,
     6     _In_ LPARAM lParam)
     7 {
     8     CWindowImplBaseT< TBase, TWinTraits >* pThis = (CWindowImplBaseT< TBase, TWinTraits >*)hWnd;
     9     // set a ptr to this message and save the old value
    10     _ATL_MSG msg(pThis->m_hWnd, uMsg, wParam, lParam);
    11     const _ATL_MSG* pOldMsg = pThis->m_pCurrentMsg;
    12     pThis->m_pCurrentMsg = &msg;
    13     // pass to the message map to process
    14     LRESULT lRes = 0;
    15     BOOL bRet = pThis->ProcessWindowMessage(pThis->m_hWnd, uMsg, wParam, lParam, lRes, 0);
    16     // restore saved value for the current message
    17     ATLASSERT(pThis->m_pCurrentMsg == &msg);
    18 
    19     // do the default processing if message was not handled
    20     if(!bRet)
    21     {
    22         if(uMsg != WM_NCDESTROY)
    23             lRes = pThis->DefWindowProc(uMsg, wParam, lParam);
    24         else
    25         {
    26             // unsubclass, if needed
    27             LONG_PTR pfnWndProc = ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC);
    28             lRes = pThis->DefWindowProc(uMsg, wParam, lParam);
    29             if(pThis->m_pfnSuperWindowProc != ::DefWindowProc && ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC) == pfnWndProc)
    30                 ::SetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC, (LONG_PTR)pThis->m_pfnSuperWindowProc);
    31             // mark window as destryed
    32             pThis->m_dwState |= WINSTATE_DESTROYED;
    33         }
    34     }
    35     if((pThis->m_dwState & WINSTATE_DESTROYED) && pOldMsg== NULL)
    36     {
    37         // clear out window handle
    38         HWND hWndThis = pThis->m_hWnd;
    39         pThis->m_hWnd = NULL;
    40         pThis->m_dwState &= ~WINSTATE_DESTROYED;
    41         // clean up after window is destroyed
    42         pThis->m_pCurrentMsg = pOldMsg;
    43         pThis->OnFinalMessage(hWndThis);
    44     }else {
    45         pThis->m_pCurrentMsg = pOldMsg;
    46     }
    47     return lRes;
    48 }

     所以,我们要么就不要注册消息对应的响应函数,注册了最好就在对应的响应函数中处理。如果非得注册而且不处理的话,就在对应的响应函数中显式的将bHandled设置为FALSE,让消息处理过程函数WindowProc执行默认的消息处理函数DefWindowProc。

  • 相关阅读:
    经典面试题目C语言
    论C语言中二级指针和二维数组之间的区别
    判断单链表中是否有环找到环的入口节点
    论decltype和auto的区别
    在ubuntu下安装opencv
    C中有关引用和指针的异同
    (四)关于读文件的结束的判别方法(EOF和feof)以及区别
    (三)论sizeof与strlen之间的区别
    (二)C语言文本流和二进制流的区别
    (一)C的编译,printf,规范化
  • 原文地址:https://www.cnblogs.com/chenyangchun/p/6782052.html
Copyright © 2011-2022 走看看