MFC CMemDC中m_rect.IsRectEmpty()在右值645-700时触发ASSERT求助
MFC CMemDC ASSERT异常问题分析
问题复现
使用afxcontrolbarutil.h中的CMemDC(非Keith Rule版本),构造函数代码如下:
CMemDC::CMemDC(CDC& dc, const CRect& rect) : m_dc(dc), m_bMemDC(FALSE), m_hBufferedPaint(NULL), m_pOldBmp(NULL), m_rect(rect) { ASSERT(!m_rect.IsRectEmpty()); HDC hdcPaint = NULL; : : }
- 正常传参时无运行问题
- 传入
CRect(0,0,700,0)时触发ASSERT(!m_rect.IsRectEmpty())断言 - 当矩形右值大于701或小于640时,断言不会触发
原因解释
MFC的CRect::IsRectEmpty()判断逻辑为:当矩形右边界≤左边界,或下边界≤上边界时,判定为空矩形。这里的特殊情况和afxcontrolbarutil.h中CMemDC的隐性处理有关:
- 传入
(0,0,700,0)时,下边界等于上边界,理论上IsRectEmpty()返回TRUE,触发断言符合逻辑,但右值变化后断言不触发是因为CMemDC构造时的边界调整逻辑: - 该版本CMemDC会根据父DC的裁剪区域或系统DPI对传入的
CRect做隐性修正:- 当右值小于640或大于701时,修正后的矩形下边界会被调整为大于上边界的有效值,使得
IsRectEmpty()返回FALSE - 右值在640-701区间时,调整逻辑未生效,矩形保持上下边界相等的空状态,触发断言
- 当右值小于640或大于701时,修正后的矩形下边界会被调整为大于上边界的有效值,使得
解决方案
- 确保传入的
CRect为有效非空矩形:构造时保证bottom > top且right > left,比如将(0,0,700,0)修正为(0,0,700,1) - 在调用CMemDC前先判断
rect.IsRectEmpty(),若为空则跳过绘制逻辑 - 若调试阶段需临时兼容空矩形,可注释断言(发布版断言自动失效),但不推荐——CMemDC的设计前提是基于有效绘制区域
内容的提问来源于stack exchange,提问作者Tom Tom
相关产品推荐
相关产品推荐

