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。

  • 相关阅读:
    Yii中缓存依赖的处理
    简单实现Tab切换(带框架)
    Server Application Unavailable出现的原因及解决方案集锦
    Microsoft.ReportViewer.WebForms, Version=10.0.0.0的报错问题,解决方案
    ASP.NET中树型DropDownList的绑定
    VS2010 使用时选择代码或双击时出错,点击窗口按钮后VS自动重启问题
    js实现文本框限制输入数字和小数点--兼容多个浏览器
    输入的全角字符转换成半角字符--css、js、ASP.NET
    sql把表格拼成字符串,多半使用于GROUP BY
    Sql将逗号分隔的字符串分拆成表格的方法
  • 原文地址:https://www.cnblogs.com/chenyangchun/p/6782052.html
Copyright © 2011-2022 走看看