MFC中为什么不用UpdateWindow也可以发送WM_PAINT消息

哈利_蜘蛛侠 2016-10-23 09:57:57
正在学习
《Ivor Horton's Beginning Visual C++ 2013》
这本书,这本书的第二部分是讲MFC的,然后遇到了一个问题。是这样的:
书上在讲在MFC中绘制的时候,是这样说的:如果要让新创造的图形被绘制出来,那么需要做这三件事情:


然而在后面给鼠标的消息做响应的时候,我发现一件奇怪的事情:在LButtonUp()中,在调用InvalidateRect()之后就马上收到了WM_PAINT消息。请问这是怎么回事呢?LButtonUp是这样写的:

void CSketcherView::OnLButtonUp(UINT nFlags, CPoint point)
{
// Make sure there is an element
if (m_pTempElement)
{
// Add the element pointer to the sketch
GetDocument()->AddElement(m_pTempElement);
InvalidateRect(&m_pTempElement->GetEnclosingRect());
m_pTempElement.reset(); // Reset the element pointer
}
}
...全文
790 20 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
schlafenhamster 2016-11-21
  • 打赏
  • 举报
回复
CDC::GetClipBox virtual int GetClipBox( LPRECT lpRect ) const; Return Value The clipping region’s type. It can be any of the following values: COMPLEXREGION Clipping region has overlapping borders. ERROR Device context is not valid. NULLREGION Clipping region is empty. SIMPLEREGION Clipping region has no overlapping borders. Parameters lpRect Points to the RECT structure or CRect object that is to receive the rectangle dimensions. Remarks Retrieves the dimensions of the tightest bounding rectangle around the current clipping boundary. The dimensions are copied to the buffer pointed to by lpRect.
哈利_蜘蛛侠 2016-11-20
  • 打赏
  • 举报
回复
引用 13 楼 zzz3265 的回复:
创建一个空的窗体, 什么代码都不写, 一样会有WM_PAINT消息 系统的窗体机制本来就是这样的 楼上也说了InvalidateRect 会导致系统会生成WM_PAINT消息, 但是会延后 我上面是解释UpdateWindow 在某些时候的必要性, 也是你引用文章所表达的意思
还有一个问题: View类的OnDraw函数应该怎么写才能够使用UpdateRegion的信息呢?
worldy 2016-10-29
  • 打赏
  • 举报
回复
mfc框架处理WM_PAINT消息代码会调用OnDraw的虚拟函数,你应该重新你自己版本的OnDraw以实现你的展示
schlafenhamster 2016-10-27
  • 打赏
  • 举报
回复
10楼的例子不是说明白了吗?
哈利_蜘蛛侠 2016-10-27
  • 打赏
  • 举报
回复
引用 15 楼 jiu6332356 的回复:
UpdateWindow 是你想让他刷新窗口 所以会调用 你说的调用应该是自动调用的 你可以调试下 只要鼠标移动就会调用onpaint函数
鼠标移动是不会受到WM_PAINT消息的,这个例子就是鼠标按下并拖动就是在绘图,鼠标松开则绘图完成;只有在鼠标松开的时候才会调用OnDraw()函数。
jiu6332356 2016-10-27
  • 打赏
  • 举报
回复
UpdateWindow 是你想让他刷新窗口 所以会调用 你说的调用应该是自动调用的 你可以调试下 只要鼠标移动就会调用onpaint函数
哈利_蜘蛛侠 2016-10-26
  • 打赏
  • 举报
回复
引用 11 楼 zzz3265 的回复:
书上的原文没说清楚导致理解有问题 InvalidateRect 调用时系统不会立即生成WM_PAINT消息, 只是做了一些标记, 然后立即返回了 UpdateWindow 是会更新窗体生成WM_PAINT消息, 等待窗体绘制完成后才返回 如果你在 InvalidateRect 后立即截图可能会看到截取的图像是不对的, 用了UpdateWindow后可以保证图形显示完成
然后这个跟我的问题有何关系呢?我这里并没有调用UpdateWindow呀
Yofoo 2016-10-26
  • 打赏
  • 举报
回复
书上的原文没说清楚导致理解有问题 InvalidateRect 调用时系统不会立即生成WM_PAINT消息, 只是做了一些标记, 然后立即返回了 UpdateWindow 是会更新窗体生成WM_PAINT消息, 等待窗体绘制完成后才返回 如果你在 InvalidateRect 后立即截图可能会看到截取的图像是不对的, 用了UpdateWindow后可以保证图形显示完成
OnTheWay_Boy 2016-10-26
  • 打赏
  • 举报
回复
WM_PAINT 只是一个消息id,调用onpaint函数,view类,隐式转换为ondraw函数 mfc机制认为需要重绘view的时候,就会发送WM_PAINT消息,所以onsize,UpdateWindow等等会发送WM_PAINT消息 但有的时候,用户自定义,需要改变视图,这个时候mfc不知道该不该重绘视图,所以需要用户自己调用Invalidate()等会发送WM_PAINT消息的函数,重绘view 所以是我理解错了楼主的意思,还是楼主应该了解下windows的消息机制
Yofoo 2016-10-26
  • 打赏
  • 举报
回复
创建一个空的窗体, 什么代码都不写, 一样会有WM_PAINT消息 系统的窗体机制本来就是这样的 楼上也说了InvalidateRect 会导致系统会生成WM_PAINT消息, 但是会延后 我上面是解释UpdateWindow 在某些时候的必要性, 也是你引用文章所表达的意思
schlafenhamster 2016-10-25
  • 打赏
  • 举报
回复
UpdateWindow 只有窗口无效时 才 起作用 ,他是用来 窗口 无效后 立即 更新窗口用的。 下面的代码 说明 它的用处 //afxDump << "OnPaint\n"; CDialog::OnPaint();// 这里 对话框 已经 使 m_Pic2 窗口无效了,但 m_Pic2 的重绘 发生在 OnPaint 后! // CStatic m_Pic2; m_Pic2.UpdateWindow();// 所以 我们调用 这个函数 让 m_Pic2 重绘,重绘 后 m_Pic2 窗口有效 CDC *picDC=m_Pic2.GetDC();// 然后 我们 取 m_Pic2 的 客户DC , CRect rc; m_Pic2.GetClientRect(rc); // FillPoints(picDC,rc,0,RGB(0,255,255));// 并在 m_Pic2 上 绘图。 // ReleaseDC(picDC);// 这就是 在 对话框 中 绘制 对话框中的 控件。 }
coolooooooo 2016-10-24
  • 打赏
  • 举报
回复
其实这些问题,你下载一个c++6.0调试跟进去看就懂了
coolooooooo 2016-10-24
  • 打赏
  • 举报
回复
因为响应wm_paint消息函数,函数会调用ondraw
赵4老师 2016-10-24
  • 打赏
  • 举报
回复
建议楼主学会使用Spy++
哈利_蜘蛛侠 2016-10-24
  • 打赏
  • 举报
回复
引用 5 楼 worldy 的回复:
InvalidateRect,本质就是投递WM_PAINT消息到线程的消息队列中,WM_PAINT是低优先级消息,可能会延迟及合并处理 UpdateWindow也是使用WM_PAINT消息但它是调用窗口函数,因此会立即得到执行
原来是这样吗?跟书上说的好像有点不一样啊。不过真这样的话那我就明白了。不过还有问题:书上的view类的OnDraw()函数是这样实现的:

void CSketcherView::OnDraw(CDC* pDC)
{
	CSketcherDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	// Draw the sketch
	for (const auto& pElement : *pDoc)
	{
		if (pDC->RectVisible(pElement->GetEnclosingRect()))
			pElement->Draw(pDC);
	}
}
这个是不是并没有用到WM_PAINT消息的update region信息呀?如果是的话,那么怎么利用这个update region信息呢?
worldy 2016-10-24
  • 打赏
  • 举报
回复
InvalidateRect,本质就是投递WM_PAINT消息到线程的消息队列中,WM_PAINT是低优先级消息,可能会延迟及合并处理 UpdateWindow也是使用WM_PAINT消息但它是调用窗口函数,因此会立即得到执行
哈利_蜘蛛侠 2016-10-24
  • 打赏
  • 举报
回复
引用 3 楼 accessysq 的回复:
InvalidateRect(&m_pTempElement->GetEnclosingRect()); 你这里标记的无效区域如果存在,系统就会发送WM_PAINT的。所以你说的问题是很正常的啊。
不可能是每调用一次InvalidateRect()就会发送这个消息吧,因为可能连续多次调用了这个函数的。而且书上也说了,要再调用UpdateWindow()才行的。
  • 打赏
  • 举报
回复
InvalidateRect(&m_pTempElement->GetEnclosingRect()); 你这里标记的无效区域如果存在,系统就会发送WM_PAINT的。所以你说的问题是很正常的啊。
哈利_蜘蛛侠 2016-10-23
  • 打赏
  • 举报
回复
引用 1 楼 qq407311984 的回复:
因为重绘窗口或者刷新窗口都会发送wm_paint消息通知程序
然而我只是松开了鼠标而已。拖动鼠标的过程中不会,尽管这时候也发生了绘制的行为。具体的比较复杂,如果你看过这本书的话就知道了。我觉得就应该是调用了InvalidateRect()的缘故,至于为何没有调用UpdateWindow()就发送了WM_PAINT消息,我觉得可能是在基类的某个地方调用了吧。
coolooooooo 2016-10-23
  • 打赏
  • 举报
回复
因为重绘窗口或者刷新窗口都会发送wm_paint消息通知程序

16,548

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • AIGC Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧