MFC点击属性页确定按钮后,屏蔽窗口自动刷新问题。

本文探讨了在MFC框架下如何有效管理视图的刷新,特别是在对话框中修改对象属性后的视图更新策略。作者详细记录了在对话框OnOK函数中控制视图刷新的过程及遇到的问题,包括闪烁现象和重绘问题,并提出了解决方案。

 

环境:VS2010

任务:修改一个属性页对话框。

操作:双击一个对象,弹出一个属性页对话框,点击确定按钮,在OnOK函数里面,设置对象的一些属性,并把这个视图刷新一遍。

描述:

这个OnOk相应函数是别人已经写好的,我把OnOK函数里面的Invalidate()和updateWindow()函数删除掉,因为我在外面也需要修改对象的一些属性,可以一起绘制,避免产生闪烁。

CDialog dlg;
if (dlg.DoMode() == IDOK)
{
	pObj->SetColor(RGB(0, 0, 255))
	CView *pView = GetActiveView();
	pView->Invalidate();
	pView->UpdateWindow();
}

应该没什么问题吧,可是问题来了。

当我点击确定按钮后,我原本以为不会产生OnPaint消息,但是确实产生了,还没有执行到代码4初,就已经产出了OnPaint消息,仔细一看,是RedrawWindow()函数引起的,这个函数是MFC内部调用的。

想了一会后,有了一个办法。

CView *pView = GetActiveView();
CMyDialog dlg;

pView->SendMessage(WM_SETREDRAW, 1, 0);//禁止视图重绘
if (dlg.DoMode() == IDOK)
{
	pView->SendMessage(WM_SETREDRAW, 0, 0);//开启视图重绘
	pObj->SetColor(RGB(0, 0, 255))

	//一起绘制
	pView->Invalidate();
	pView->UpdateWindow();
}

这样应该没有问题了吧!确实是解决问题了,可以新的问题又来了,悲剧了,移动属性页对话框也不能重绘窗口,界面简直惨不忍睹啊。后来我跟踪了一下,RedrawWindow()函数是在身什么时候调用的,他在OnOK函数执行完之后,在CMyDialog的析构函数执行之前,我们可以这样做。m_pView是成员变量,不能通过GetParent()获得视图对象,因为在执行CMyDialog的析构函数时,得到的指针为NULL,我们可以存储一个成员变量。

CMyDialog::OnOK()
{
	m_pView->SendMessage(WM_SETREDRAW, 1, 0);//禁止视图重绘
}

CMyDialog::~OnOK()
{
	m_pView->SendMessage(WM_SETREDRAW, 0, 0);//开启视图重绘
}

总结:

不应该在对话框的响应函数里面直接修改对象,应该在相应函数里面存储这些属性到成员变量中,执行DoMode后,从CMyDialog中取出这些属性,最后设置到对象中。

<think>好的,用户想在VC6.0的MFC应用程序中实现点击按钮刷新窗口的功能。首先,我需要回忆一下MFC的基本结构和消息处理机制。MFC中,按钮点击会发送BN_CLICKED消息,所以用户需要为按钮添加一个消息处理函数。 接下来,刷新窗口通常涉及到重绘。在MFC中,常用的方法是调用Invalidate()或InvalidateRect()来触发窗口的重绘。Invalidate()会使整个客户区无效,导致WM_PAINT消息被发送,而InvalidateRect()可以指定特定的区域。可能还需要调用UpdateWindow()来立即重绘,但一般情况下,Invalidate()后系统会自动处理WM_PAINT。 然后,用户需要在按钮点击事件处理函数里调用这些方法。比如,在OnButtonClick函数中,先调用Invalidate(TRUE)来清空背景,或者FALSE保持背景,再可能需要UpdateWindow()。不过有时候直接Invalidate()就足够了,因为WM_PAINT会被加入消息队列,但优先级较低,所以可能需要UpdateWindow()来强制立即重绘。 另外,用户可能需要检查是否正确关联了按钮的消息处理函数。在VC6.0中,可以通过ClassWizard来添加BN_CLICKED的处理函数,确保函数被正确绑定,并且函数内部调用了Invalidate()等方法。 还有,窗口刷新可能涉及到OnPaint()函数的重写。用户需要确认在视图类或对话框类中,OnPaint()方法是否正确实现了绘制逻辑,这样当Invalidate()被调用时,OnPaint()会执行重绘操作。 可能的误区是用户忘记调用Invalidate(),或者错误地调用了其他函数。另外,如果窗口中有很多控件,可能需要使用RedrawWindow()函数,它结合了Invalidate()和UpdateWindow()的功能,并且可以控制更多的重绘选项。 还需要考虑窗口刷新的性能问题,如果频繁调用Invalidate(),可能会导致界面闪烁。这时候可以尝试使用双缓冲技术,或者在Invalidate()时指定特定的区域来减少重绘的面积。 最后,建议用户按照步骤检查:添加按钮的消息处理函数,调用Invalidate()或相关函数,确保OnPaint()正确绘制。如果仍有问题,检查是否有其他代码阻塞了消息循环,或者绘制逻辑有错误。</think>在VC6.0 MFC中通过按钮点击刷新窗口,可通过以下步骤实现: 1. **创建消息映射函数** 打开ClassWizard (Ctrl+W) → 选择按钮的ID → 添加`BN_CLICKED`消息处理函数 2. **编写按钮点击事件代码** 在自动生成的`OnButtonX()`函数中插入窗口刷新代码: ```cpp void CMyDialog::OnButtonRefresh() { // 方法1:强制立即重绘 Invalidate(TRUE); // TRUE表示擦除背景 UpdateWindow(); // 立即发送WM_PAINT消息 // 方法2:区域刷新(更高效) CRect rect; GetClientRect(&rect); InvalidateRect(rect, TRUE); // 仅刷新指定区域 } ``` 3. **重写绘制逻辑** 在视图/对话框类中实现`OnPaint()`函数: ```cpp void CMyView::OnPaint() { CPaintDC dc(this); // 在此处添加自定义绘制代码 dc.TextOut(10, 10, _T("刷新后的内容")); } ``` **注意事项:** - `Invalidate()`标记需要重绘的区域,`UpdateWindow()`强制立即处理WM_PAINT - 使用`InvalidateRect()`可优化性能,仅重绘指定区域 - 频繁刷新时建议开启双缓冲防止闪烁: ```cpp // 在OnPaint()中: CDC memDC; memDC.CreateCompatibleDC(&dc); CBitmap bmp; bmp.CreateCompatibleBitmap(&dc, rect.Width(), rect.Height()); // 绘制到memDC后复制到屏幕DC ``` **调试技巧:** 1. 在`OnPaint()`中设置断点,确认是否被触发 2. 检查消息映射宏是否正确定义: ```cpp BEGIN_MESSAGE_MAP ON_BN_CLICKED(IDC_BUTTON1, OnButtonRefresh) END_MESSAGE_MAP ``` 3. 若使用对话框,确保未设置`WS_CLIPCHILDREN`样式 通过上述方法可实现安全可靠的窗口刷新操作,建议优先使用区域刷新(InvalidateRect)优化性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值