atlwin中不停发WM_PAINT消息原因分析
这里我们基于atlwin定义的窗口类SampleWindow继承自CWindowImpl(定义见atlwin.h),并注册了WM_PAINT消息处理函数OnPaint,注意,我们在OnPaint函数中并没有直接处理WM_PAINT消息,而是直接返回了FALSE。
class SampleWindow : public CWindowImpl<SampleWindow> {
public:
SampleWindow():
DECLARE_WND_SUPERCLASS(_T("SampleWindow"), NULL)
BEGIN_MSG_MAP(SampleWindow)
MESSAGE_HANDLER(WM_PAINT, OnPaint)
END_MSG_MAP()
LRESULT OnPaint(UINT msg, WPARAM wparam, LPARAM lparam, BOOL &handled)
{
return FALSE;
}
}
参考MESSAGE_HANDLER的宏定义就会发现,在执行对应的消息响应函数之前,bHandled默认被赋值为了TRUE(所以通常情况下WM_PAINT消息需要在这里处理),但是参照上述代码,OnPaint函数并未对WM_PAINT消息处理,并且直接返回了FALSE,而MESSAGE_HANDLER默认是返回TRUE的。
#define MESSAGE_HANDLER(msg, func) \
if(uMsg == msg) \
{ \
bHandled = TRUE; \
lResult = func(uMsg, wParam, lParam, bHandled); \
if(bHandled) \
return TRUE; \
}
在代码执行到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消息未得到处理),造成死循环。
template <class TBase, class TWinTraits>
LRESULT CALLBACK CWindowImplBaseT< TBase, TWinTraits >::WindowProc(
_In_ HWND hWnd,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam)
{
CWindowImplBaseT< TBase, TWinTraits >* pThis = (CWindowImplBaseT< TBase, TWinTraits >*)hWnd;
// set a ptr to this message and save the old value
_ATL_MSG msg(pThis->m_hWnd, uMsg, wParam, lParam);
const _ATL_MSG* pOldMsg = pThis->m_pCurrentMsg;
pThis->m_pCurrentMsg = &msg;
// pass to the message map to process
LRESULT lRes = ;
BOOL bRet = pThis->ProcessWindowMessage(pThis->m_hWnd, uMsg, wParam, lParam, lRes, );
// restore saved value for the current message
ATLASSERT(pThis->m_pCurrentMsg == &msg); // do the default processing if message was not handled
if(!bRet)
{
if(uMsg != WM_NCDESTROY)
lRes = pThis->DefWindowProc(uMsg, wParam, lParam);
else
{
// unsubclass, if needed
LONG_PTR pfnWndProc = ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC);
lRes = pThis->DefWindowProc(uMsg, wParam, lParam);
if(pThis->m_pfnSuperWindowProc != ::DefWindowProc && ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC) == pfnWndProc)
::SetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC, (LONG_PTR)pThis->m_pfnSuperWindowProc);
// mark window as destryed
pThis->m_dwState |= WINSTATE_DESTROYED;
}
}
if((pThis->m_dwState & WINSTATE_DESTROYED) && pOldMsg== NULL)
{
// clear out window handle
HWND hWndThis = pThis->m_hWnd;
pThis->m_hWnd = NULL;
pThis->m_dwState &= ~WINSTATE_DESTROYED;
// clean up after window is destroyed
pThis->m_pCurrentMsg = pOldMsg;
pThis->OnFinalMessage(hWndThis);
}else {
pThis->m_pCurrentMsg = pOldMsg;
}
return lRes;
}
所以,我们要么就不要注册消息对应的响应函数,注册了最好就在对应的响应函数中处理。如果非得注册而且不处理的话,就在对应的响应函数中显式的将bHandled设置为FALSE,让消息处理过程函数WindowProc执行默认的消息处理函数DefWindowProc。
atlwin中不停发WM_PAINT消息原因分析的更多相关文章
- Invalidate(TRUE)与Invalidate(FALSE)区别(前者会发送WM_ERASEBKGND消息全部刷新,然后使用WM_PAINT消息绘制,而后者只发送WM_PAINT消息)
使用Invalidate(TRUE)函数时,它会向消息队列中添加了WM_ERASEBKGND和WM_PAINT两个消息. 使用Invalidate(FALSE)函数时,它只会向消息队列中添加了WM_P ...
- RocketMQ 消息发送system busy、broker busy原因分析与解决方案
目录 1.现象 2.原理解读 2.1 RocketMQ 网络处理机制概述 2.2 pair.getObject1().rejectRequest() 2.3 漫谈transientStorePoolE ...
- 【FAQ】接入HMS Core推送服务,服务端下发消息常见错误码原因分析及解决方法
HMS Core推送服务支持开发者使用HTTPS协议接入Push服务端,可以从服务器发送下行消息给终端设备.这篇文章汇总了服务端下发消息最常见的6个错误码,并提供了原因分析和解决方法,有遇到类似问题的 ...
- JavaScript中的ParseInt("08")和“09”返回0的原因分析及解决办法
今天在程序中出现一个bugger ,调试了好久,最后才发现,原来是这个问题. 做了一个实验: alert(parseInt("01")),当这个里面的值为01====>07时 ...
- 在Android library中不能使用switch-case语句访问资源ID的原因分析及解决方案
转自:http://www.jianshu.com/p/89687f618837 原因分析 当我们在Android依赖库中使用switch-case语句访问资源ID时会报如下图所示的错误,报的错误 ...
- ORACLE中order by造成分页不正确原因分析
工作中遇到的问题: 为调用方提供一个分页接口时,调用方一直反应有部分数据取不到,且取到的数据有重复的内容,于是我按以下步骤排查了下错误. 1.检查分页页码生成规则是否正确. 2.检查SQL语句是否正 ...
- PHP switch分支语句中省略break后还会执行其他case的原因分析
请分析以下PHP代码的输出结果: $a= 'dog'; switch($a) { case 'cat': echo "\$a is cat"; case 'dog': echo & ...
- WM_PAINT产生原因有2种(用户操作和API)——WM_PAINT和WM_ERASEBKGND产生时的先后顺序不一定(四段讨论)
1. 当WM_PAINT不是由InvalidateRect产生时,即由最大化,最小化等产生时,或者移动产生(移动有时只会产生WM_ERASEBKGND消息)系统先发送WM_ERASEBKGND消息,再 ...
- WM_PAINT消息详解,使用InvalidateRect或InvalidateRgn函数刻意产生WM_PAINT消息(WIN7里有变化,“调整视觉效果”,将“启用桌面组合”去掉)
什么时候会触发WM_PAINT消息消息呢? 以下内容来自大名鼎鼎的<Windows程序设计(第五版)> 大多数Windows程序在WinMain中进入消息循环之前的初始化期间都要呼叫函数U ...
随机推荐
- iOS开发之 Lottie -- 炫酷的动效
动效在软件开发中非常常见,炫酷的动画能提升应用的B格,然而由设计师的设计转化成程序猿GG的代码是个非常"痛苦"的过程.对于复杂动画,可能要花费很多时间去研究和实现.Lottie 的 ...
- SDN学习之实现环路通信
在对OpenFlow协议有了一定了解以后,开始尝试如何通过Ryu控制器实现网络中的通信.根据协议,我们知道,当数据信息首次传输到交换机时,由于交换机不存在该数据信息所对应的流表,因此,会触发Packe ...
- android Activity Application Context 的区别
用了这么久的Context,对于Context究竟是个什么玩意一直不是很明白.看了网上十几篇文章的介绍 加上自己的理解总结一下.(自己想法,不对勿喷,不想照搬网上一些文字说法来糊弄自己,自己理解的就这 ...
- android打电话
一.安卓中,TelephonyManager是电话管理器,它管理着电话的所有服务. 1.如图,为一个简单的打电话应用,他是通过调用系统API实现的,必须添加权限 2.先看清单文件,此处添加权限 < ...
- APUE-文件和目录(五)函数rename和renameat
rename和renameat #include <stdio.h> int rename(const char *oldname,const char*newname); int ren ...
- Canvas学习系列一:初识canvas
最近你开始在学习canvas,打算把学习canvas的整个学习过程当中的一些笔记与总结记录下来,如有什么不足之处还请大神们多多指出. 1. 认识canvas Canvas元素的出现,可以说开启的Web ...
- Awesome Hadoop
A curated list of amazingly awesome Hadoop and Hadoop ecosystem resources. Inspired by Awesome PHP, ...
- tcp/ip详解 卷1 -- 协议概述
第一章 概述 分层 TCP/IP 通常被认为是一个四层协议系统. 每一层负责不同的功能. 链路层, 也成为数据链路层或者网络接口层. 通常包括 操作系统中的设备驱动程序和计算机中对应的网络接口卡. 主 ...
- twemproxy代理主干流程——剖析twemproxy代码正编
在twemproxy的发送和接收流程剖析中,我们已经完全弄清楚twemproxy如何将客户端以及服务端发来的包切分成msg,获得一个独立的msg后twemproxy应该如何处理?这是本文这次需要重点介 ...
- 【Python3之异常处理】
一.错误和异常 1.错误 代码运行前的语法或者逻辑错误 语法错误(这种错误,根本过不了python解释器的语法检测,必须在程序执行前就改正) def test: ^ SyntaxError: inva ...