单说CArchive,在单文档应用程序中确实方便,但是要是MFC做得是辅助程序,比如地图编辑器,那么生成的文档必然不能在游戏中用,若要用的话得引入MFC库,凭空使程序增加了大小。
单文档ID_File_New 根据我的理解 会调用CWinApp::OnfileNew ,然后CwinApp::OnfileNew 调用 CDocument::OnNewDocument 这个就不用改了。
注意:经过我的实验OnNewDocument是不能用 afx_msg映射的
CwinApp::OnFIleOpen 也是这样都会调用CDocument::OnOpenDocument(name) 注意,CDocument::OnOpenDocument 会调用serilize()函数,这样会串行化,所以在覆盖的时候不要调用CDocument::OnOpenDocument, 那个传入的name 就是弹出CFIleDilog中文件的名字,我估计那个弹出对话框的工作是CWinApp::OnOpenFile()做得。
至于CDocument::OnFileSave() 这个的对话框显示是CDocument做得,也会调用serilize()函数,所以覆盖的时候不要调用基类的OnFileSave就行了,至于对话框的显示,自己做一个吧,就用CFileDialog,很简单。
后面说说OnUpdateAllViews()
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.csdn.net/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用于cdialogonpait 响应WM_PAINT消息,在CView中,它接着调用OnDraw CPaintDC响应wm_paint消息,自动完成绘制 ClientDC实时绘制一般情况下,你看不到两个函数有什么太大区别,因为一般情况下,它们的任务都是重画窗口。
在CView及其子类中,恰如浪刀所言,OnDraw是由OnPaint调用的,也就是你可以像在窗口类中一样,调用Invalidate函数导致,OnDraw的调用(当然,Invalidate是先导致OnPaint的调用)。 要说OnDraw和OnPaint有什么区别,那就是它除了可以把画画到屏幕外,还可以把它画到其它任何标准输出设备,如打印机
最后再说下OnUpdate()
CView::OnUpdatevirtual void OnUpdate( CView* pSender, LPARAM lHint, CObject* pHint );
参数:
pSender 指向修改了文档的视图,如果需要更新所有的视图,则为NULL。 lHint 包含了与修改有关的信息。 pHint 指向保存了与修改有关的信息的对象。
说明:框架在视图的文档被修改后调用这个函数;这个函数CDocument::UpdateAllViews调用的,使视图能够更新它的显示以反映那些变化。它也被OnInitialUpdate的缺省实现所调用。缺省的实现使整个客户区域无效,使得下一次接收到WM_PAINT消息时重画这些区域。如果你只想更新与文档的修改部分对应的区域,则应重载这个函数。为此你必须利用提示参数传递有关修改的信息。如果要使用lHint,则应定义特殊的提示值,通常是位掩码或枚举值,并且使文档传递其中的一个值。要使用pHint,则应从CObject集成一个提示类,并使文档传递提示对象的指针。当你重载OnUpdate函数的时候,应使用CObject::IsKindOf成员函数来确定提示对象的运行时类型。通常你不用在OnUpdate中直接执行任何绘图操作。相反,确定以设备坐标表示的矩形,描述要更新的区域,将这个矩形传递给CWnd::InvalidateRect。这会使下一次接收到WM_PAINT消息时产生绘图操作。如果lHint为0,pHint为NULL,文档将发送一个一般的更新通知。如果一个视图接收到了一般的更新通知,或者它没有解码出提示,它将会使整个客户区无效。
没有评论:
发表评论