Invalidate()与UpdateAllViews

本文深入解析了MFC框架下Invalidate()和UpdateAllViews()函数的区别与应用场景,详细解释了两者如何影响窗口重绘及文档与视图之间的交互。通过对比分析,帮助开发者理解在不同场景下选择合适的方法实现界面更新。

Invalidate()是让程序重画窗口。
UpdateAllViews()是在DOC/VIEW结构中,
当一个视图的数据改变后,
通知所有视图作相应的改变,
和重画毫无关系。

Invalidate()是使窗口无效,使系统向其发WM_PAINT消息,使的程序的OnPaint被调用重画客户区。

而UpdateAllViews()是文档与视图之间的联系,调用从它会使程序与此文档相关的所有视图的UpdateView被调用至于是否

重画怎么画是由各视图的UpdateView来决定的。

Invalidate()是Cwnd的成员函数,与DOC-VIEW无关;
UpdateAllViews是CDocument的成员函数,具体体现DOC-VIEW的精神。
如果仅重画当前窗口用 this->Invalidate();
如果通知所有和当前文档相关的窗口重画用GetDocument()->UpdateAllViews()(在View中)或this->UpdateAllViews()

(在Doc中)。

Invalidate()函数产生一条WM_PAINT消息,并送入windows消息队列中,是窗口产生重画。
而,UpdateAllViews 并不进入windows消息队列中,直接产生重画


*******************************************

Invalidate函数的总结

InvalidateRect只是增加重绘区域,在下次WM_PAINT的时候才生效

InvalidateRect函数中的参数TRUE表示系统会在你画之前用背景色将所选区域覆盖一次,默认背景色为白色,可以通过

设置BRUSH来改变背景色。

Invalidate()之后:(MFC的,顺便了)
OnPaint()->OnPrepareDC()->OnDraw()
所以只是刷新在OnPaint()和OnDraw()函数中的绘图语句。其它地方没有影响。

Invalidate标记一个需要重绘的无效区域,并不意味着调用该函数后就立刻进行重绘。类似于PostMessage(WM_PAINT),

需要处理到WM_PAINT消息时才真正重绘。以为您Invalidate之后还有其他的语句正在执行,程序没有机会去处理

WM_PAINT消息,但当函数执行完毕后,消息处理才得以进行。

Invalidate只是放一个WM_PAINT消息在队列里,不做别的,所以只有当当前函数返回后,进入消息循环,取出

WM_PAINT,才执行PAINT,所以不管Invalidate放哪里,都是最后的。

InvalidateRect(hWnd,&rect,TRUE);向hWnd窗体发出WM_PAINT的消息,强制客户区域重绘制,
rect是你指定要刷新的区域,此区域外的客户区域不被重绘,这样防止客户区域的一个局部的改动,而导致整个客户区域重绘

而导致闪烁,如果最后的参数为TRUE,则还向窗体发送WM_ERASEBKGND消息,使背景重绘,当然在客户区域重绘之前。
UpdateWindow只向窗体发送WM_PAINT消息,在发送之前判断GetUpdateRect(hWnd,NULL,TRUE)看有无可绘制的客户区

域,如果没有,则不发送WM_PAINT

如果希望立即刷新无效区域,可以在调用InvalidateRect之后调用UpdateWindow,如果客户区的任一部分无效,则

UpdateWindow将导致Windows用WM_PAINT消息调用窗口过程(如果整个客户区有效,则不调用窗口过程)。

这一WM_PAINT消息不进入消息队列,直接由WINDOWS调用窗口过程。窗口过程完成刷新以后立刻退出,

WINDOWS将控制返回给程序中UpdateWindow调用之后的语句。(windows程序设计第5版 P98)

UpdateData()顺便说下,这个函数不是刷新界面用的。
UpdateData();参数为FALSE时,将界面上控件绑定的变量的数据导到控件内,参数为TRUE时,导入方向则相反。

Trackback:http://tb.blog.youkuaiyun.com/TrackBack.aspx?PostId=1618571

onDraw和onPaint函数的区别

CWnd::OnPaint() 是CWnd类的成员函数,是WM_PAINT 消息的响应函数.当你调用

CWnd::UpdateWindow(),CWnd::RedrawWindow()时, 或者窗口被其他窗口覆盖,改变大小等事件就会产生WM_PAINT 消息.

你可以在CWnd派生的子类中使用它.

CView::OnDraw()是CView类的一个纯虚函数.你要使用,必须重载它.
CView::OnPaint()会调用它.
OnPaint是收到WM_PAINT消息时所调用的,OnPaint调用OnDraw函数,而由于OnDraw是虚拟函数,你可以自己改写,

所以就实现了,不同的绘图目的
ondraw用于cview,而onpaint用于cdialog

onpait 响应WM_PAINT消息,在CView中,它接着调用OnDraw
CPaintDC响应wm_paint消息,自动完成绘制
ClientDC实时绘制

一般情况下,你看不到两个函数有什么太大区别,因为一般情况下,它们的任务都是重画窗口。
在CView及其子类中,恰如浪刀所言,OnDraw是由OnPaint调用的,也就是你可以像在窗口类中一样,调用Invalidate

函数导致,OnDraw的调用(当然,Invalidate是先导致OnPaint的调用)。
要说OnDraw和OnPaint有什么区别,那就是它除了可以把画画到屏幕外,还可以把它画到其它任何标准输出设备,

如打印机

详情参考 viewcore.cpp 吧

下载自:百度文库

#include "pch.h" #include "RecursiveSphereDemo.h" #include "LeftPortion.h" #include "RecursiveSphereDemoDoc.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // CLeftPortion IMPLEMENT_DYNCREATE(CLeftPortion, CFormView) CLeftPortion::CLeftPortion() : CFormView(CLeftPortion::IDD) { // TODO: 在此添加构造代码 } CLeftPortion::~CLeftPortion() { } void CLeftPortion::DoDataExchange(CDataExchange* pDX) { CFormView::DoDataExchange(pDX); DDX_Control(pDX, IDC_SLIDER_RADIUS, m_sliderRadius); DDX_Control(pDX, IDC_SLIDER_LEVEL, m_sliderSubdivision); // 对应资源中的 LEVEL DDX_Control(pDX, IDC_RADIO_WIREFRAME, m_radioWireframe); DDX_Control(pDX, IDC_RADIO_SURFACE, m_radioSurface); DDX_Control(pDX, IDC_RADIO_LIGHT_OFF, m_radioLightOff); DDX_Control(pDX, IDC_RADIO_LIGHT_ON, m_radioLightOn); DDX_Control(pDX, IDC_SLIDER_TRANS_X, m_sliderTranslateX); // 对应资源中的 TRANS_X DDX_Control(pDX, IDC_SLIDER_TRANS_Y, m_sliderTranslateY); // 对应资源中的 TRANS_Y DDX_Control(pDX, IDC_SLIDER_TRANS_Z, m_sliderTranslateZ); // 对应资源中的 TRANS_Z DDX_Control(pDX, IDC_EDIT_TRANSLATE_X, m_editTranslateX); DDX_Control(pDX, IDC_EDIT_TRANSLATE_Y, m_editTranslateY); DDX_Control(pDX, IDC_EDIT_TRANSLATE_Z, m_editTranslateZ); DDX_Control(pDX, IDC_SLIDER_ROT_X, m_sliderRotateX); // 对应资源中的 ROT_X DDX_Control(pDX, IDC_SLIDER_ROT_Y, m_sliderRotateY); // 对应资源中的 ROT_Y DDX_Control(pDX, IDC_SLIDER_ROT_Z, m_sliderRotateZ); // 对应资源中的 ROT_Z DDX_Control(pDX, IDC_EDIT_ROTATE_X, m_editRotateX); DDX_Control(pDX, IDC_EDIT_ROTATE_Y, m_editRotateY); DDX_Control(pDX, IDC_EDIT_ROTATE_Z, m_editRotateZ); } BEGIN_MESSAGE_MAP(CLeftPortion, CFormView) ON_WM_HSCROLL() ON_BN_CLICKED(IDC_RADIO_WIREFRAME, &CLeftPortion::OnBnClickedRadioWireframe) ON_BN_CLICKED(IDC_RADIO_SURFACE, &CLeftPortion::OnBnClickedRadioSurface) ON_BN_CLICKED(IDC_RADIO_LIGHT_OFF, &CLeftPortion::OnBnClickedRadioLightOff) ON_BN_CLICKED(IDC_RADIO_LIGHT_ON, &CLeftPortion::OnBnClickedRadioLightOn) ON_EN_CHANGE(IDC_EDIT_TRANSLATE_X, &CLeftPortion::OnEnChangeEditTranslateX) ON_EN_CHANGE(IDC_EDIT_TRANSLATE_Y, &CLeftPortion::OnEnChangeEditTranslateY) ON_EN_CHANGE(IDC_EDIT_TRANSLATE_Z, &CLeftPortion::OnEnChangeEditTranslateZ) ON_EN_CHANGE(IDC_EDIT_ROTATE_X, &CLeftPortion::OnEnChangeEditRotateX) ON_EN_CHANGE(IDC_EDIT_ROTATE_Y, &CLeftPortion::OnEnChangeEditRotateY) ON_EN_CHANGE(IDC_EDIT_ROTATE_Z, &CLeftPortion::OnEnChangeEditRotateZ) END_MESSAGE_MAP() BOOL CLeftPortion::PreCreateWindow(CREATESTRUCT& cs) { // TODO: 在此处通过修改 CREATESTRUCT cs 来修改窗口类或样式 return CFormView::PreCreateWindow(cs); } void CLeftPortion::OnInitialUpdate() { CFormView::OnInitialUpdate(); // 获取文档指针 CRecursiveSphereDemoDoc* pDoc = GetDocument(); if (!pDoc) return; // 设置滑块范围和初始值 // 球体控制 m_sliderRadius.SetRange(1, 100); m_sliderRadius.SetPos((int)(pDoc->m_fRadius * 100)); m_sliderSubdivision.SetRange(0, 4); // 细分级别范围(0-4) m_sliderSubdivision.SetPos(pDoc->m_nSubdivision); // 平移变换 m_sliderTranslateX.SetRange(-100, 100); m_sliderTranslateX.SetPos((int)(pDoc->m_fTranslateX * 100)); m_sliderTranslateY.SetRange(-100, 100); m_sliderTranslateY.SetPos((int)(pDoc->m_fTranslateY * 100)); m_sliderTranslateZ.SetRange(-100, 100); m_sliderTranslateZ.SetPos((int)(pDoc->m_fTranslateZ * 100)); // 旋转变换 m_sliderRotateX.SetRange(-180, 180); m_sliderRotateX.SetPos((int)pDoc->m_fRotateX); m_sliderRotateY.SetRange(-180, 180); m_sliderRotateY.SetPos((int)pDoc->m_fRotateY); m_sliderRotateZ.SetRange(-180, 180); m_sliderRotateZ.SetPos((int)pDoc->m_fRotateZ); // 设置单选按钮状态 m_radioWireframe.SetCheck(pDoc->m_bWireframe ? BST_CHECKED : BST_UNCHECKED); m_radioSurface.SetCheck(!pDoc->m_bWireframe ? BST_CHECKED : BST_UNCHECKED); m_radioLightOff.SetCheck(!pDoc->m_bLighting ? BST_CHECKED : BST_UNCHECKED); m_radioLightOn.SetCheck(pDoc->m_bLighting ? BST_CHECKED : BST_UNCHECKED); // 更新UI显示 UpdateUI(); } void CLeftPortion::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { CRecursiveSphereDemoDoc* pDoc = GetDocument(); if (!pDoc) return; if (pScrollBar == &m_sliderRadius) { pDoc->m_fRadius = (float)m_sliderRadius.GetPos() / 100.0f; pDoc->UpdateAllViews(NULL); } else if (pScrollBar == &m_sliderSubdivision) { pDoc->m_nSubdivision = m_sliderSubdivision.GetPos(); pDoc->m_nTriangleCount = 8 * (int)pow(4.0, pDoc->m_nSubdivision); pDoc->UpdateAllViews(NULL); } else if (pScrollBar == &m_sliderTranslateX) { pDoc->m_fTranslateX = (float)m_sliderTranslateX.GetPos() / 100.0f; CString str; str.Format("%.2f", pDoc->m_fTranslateX); m_editTranslateX.SetWindowText(str); pDoc->UpdateAllViews(NULL); } else if (pScrollBar == &m_sliderTranslateY) { pDoc->m_fTranslateY = (float)m_sliderTranslateY.GetPos() / 100.0f; CString str; str.Format("%.2f", pDoc->m_fTranslateY); m_editTranslateY.SetWindowText(str); pDoc->UpdateAllViews(NULL); } else if (pScrollBar == &m_sliderTranslateZ) { pDoc->m_fTranslateZ = (float)m_sliderTranslateZ.GetPos() / 100.0f; CString str; str.Format("%.2f", pDoc->m_fTranslateZ); m_editTranslateZ.SetWindowText(str); pDoc->UpdateAllViews(NULL); } else if (pScrollBar == &m_sliderRotateX) { pDoc->m_fRotateX = (float)m_sliderRotateX.GetPos(); CString str; str.Format("%.0f", pDoc->m_fRotateX); m_editRotateX.SetWindowText(str); pDoc->UpdateAllViews(NULL); } else if (pScrollBar == &m_sliderRotateY) { pDoc->m_fRotateY = (float)m_sliderRotateY.GetPos(); CString str; str.Format("%.0f", pDoc->m_fRotateY); m_editRotateY.SetWindowText(str); pDoc->UpdateAllViews(NULL); } else if (pScrollBar == &m_sliderRotateZ) { pDoc->m_fRotateZ = (float)m_sliderRotateZ.GetPos(); CString str; str.Format("%.0f", pDoc->m_fRotateZ); m_editRotateZ.SetWindowText(str); pDoc->UpdateAllViews(NULL); } CFormView::OnHScroll(nSBCode, nPos, pScrollBar); } void CLeftPortion::OnBnClickedRadioWireframe() { CRecursiveSphereDemoDoc* pDoc = GetDocument(); if (pDoc) { pDoc->m_bWireframe = TRUE; pDoc->UpdateAllViews(NULL); } } void CLeftPortion::OnBnClickedRadioSurface() { CRecursiveSphereDemoDoc* pDoc = GetDocument(); if (pDoc) { pDoc->m_bWireframe = FALSE; pDoc->UpdateAllViews(NULL); } } void CLeftPortion::OnBnClickedRadioLightOff() { CRecursiveSphereDemoDoc* pDoc = GetDocument(); if (pDoc) { pDoc->m_bLighting = FALSE; pDoc->UpdateAllViews(NULL); } } void CLeftPortion::OnBnClickedRadioLightOn() { CRecursiveSphereDemoDoc* pDoc = GetDocument(); if (pDoc) { pDoc->m_bLighting = TRUE; pDoc->UpdateAllViews(NULL); } } void CLeftPortion::OnEnChangeEditTranslateX() { CRecursiveSphereDemoDoc* pDoc = GetDocument(); if (!pDoc) return; CString str; m_editTranslateX.GetWindowText(str); float fValue; if (str.GetLength() > 0 && !str.IsEmpty()) { fValue = (float)_tstof(str); if (fValue >= -1.0f && fValue <= 1.0f) { pDoc->m_fTranslateX = fValue; m_sliderTranslateX.SetPos((int)(fValue * 100)); pDoc->UpdateAllViews(NULL); } } } void CLeftPortion::OnEnChangeEditTranslateY() { CRecursiveSphereDemoDoc* pDoc = GetDocument(); if (!pDoc) return; CString str; m_editTranslateY.GetWindowText(str); float fValue; if (str.GetLength() > 0 && !str.IsEmpty()) { fValue = (float)_tstof(str); if (fValue >= -1.0f && fValue <= 1.0f) { pDoc->m_fTranslateY = fValue; m_sliderTranslateY.SetPos((int)(fValue * 100)); pDoc->UpdateAllViews(NULL); } } } void CLeftPortion::OnEnChangeEditTranslateZ() { CRecursiveSphereDemoDoc* pDoc = GetDocument(); if (!pDoc) return; CString str; m_editTranslateZ.GetWindowText(str); float fValue; if (str.GetLength() > 0 && !str.IsEmpty()) { fValue = (float)_tstof(str); if (fValue >= -1.0f && fValue <= 1.0f) { pDoc->m_fTranslateZ = fValue; m_sliderTranslateZ.SetPos((int)(fValue * 100)); pDoc->UpdateAllViews(NULL); } } } void CLeftPortion::OnEnChangeEditRotateX() { CRecursiveSphereDemoDoc* pDoc = GetDocument(); if (!pDoc) return; CString str; m_editRotateX.GetWindowText(str); float fValue; if (str.GetLength() > 0 && !str.IsEmpty()) { fValue = (float)_tstof(str); if (fValue >= -180.0f && fValue <= 180.0f) { pDoc->m_fRotateX = fValue; m_sliderRotateX.SetPos((int)fValue); pDoc->UpdateAllViews(NULL); } } } void CLeftPortion::OnEnChangeEditRotateY() { CRecursiveSphereDemoDoc* pDoc = GetDocument(); if (!pDoc) return; CString str; m_editRotateY.GetWindowText(str); float fValue; if (str.GetLength() > 0 && !str.IsEmpty()) { fValue = (float)_tstof(str); if (fValue >= -180.0f && fValue <= 180.0f) { pDoc->m_fRotateY = fValue; m_sliderRotateY.SetPos((int)fValue); pDoc->UpdateAllViews(NULL); } } } void CLeftPortion::OnEnChangeEditRotateZ() { CRecursiveSphereDemoDoc* pDoc = GetDocument(); if (!pDoc) return; CString str; m_editRotateZ.GetWindowText(str); float fValue; if (str.GetLength() > 0 && !str.IsEmpty()) { fValue = (float)_tstof(str); if (fValue >= -180.0f && fValue <= 180.0f) { pDoc->m_fRotateZ = fValue; m_sliderRotateZ.SetPos((int)fValue); pDoc->UpdateAllViews(NULL); } } } void CLeftPortion::UpdateUI() { CRecursiveSphereDemoDoc* pDoc = GetDocument(); if (!pDoc) return; // 更新编辑框 CString str; str.Format("%.2f", pDoc->m_fTranslateX); m_editTranslateX.SetWindowText(str); str.Format("%.2f", pDoc->m_fTranslateY); m_editTranslateY.SetWindowText(str); str.Format("%.2f", pDoc->m_fTranslateZ); m_editTranslateZ.SetWindowText(str); str.Format("%.0f", pDoc->m_fRotateX); m_editRotateX.SetWindowText(str); str.Format("%.0f", pDoc->m_fRotateY); m_editRotateY.SetWindowText(str); str.Format("%.0f", pDoc->m_fRotateZ); m_editRotateZ.SetWindowText(str); } CRecursiveSphereDemoDoc* CLeftPortion::GetDocument() const { return reinterpret_cast<CRecursiveSphereDemoDoc*>(m_pDocument); } 修改代码错误给出正确的完整代码
06-21
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值