Document\View\MainFrame--MessageMap

文档 视图 框架窗口间的关系和消息传送规律

在MFC中M$引入了文档-视结构的概念,文档相当于数据容器,视相当于查看数据的窗口或是和数据发生交互的窗口。(这一结构在MFC中的OLE,ODBC开发时又得到更多的拓展)因此一个完整的应用一般由四个类组成:CWinApp应用类,CFrameWnd窗口框架类,CDocument文档类,CView视类。(VC6中支持创建不带文档-视的应用)

在程序运行时CWinApp将创建一个CFrameWnd框架窗口实例,而框架窗口将创建文档模板,然后有文档模板创建文档实例和视实例,并将两者关联。一般来讲我们只需对文档和视进行操作,框架的各种行为已经被MFC安排好了而不需人为干预,这也是M$设计文档-视结构的本意,让我们将注意力放在完成任务上而从界面编写中解放出来。

在应用中一个视对应一个文档,但一个文档可以包含多个视。一个应用中只用一个框架窗口,对多文档界面来讲可能有多个MDI子窗口。每一个视都是一个子窗口,在单文档界面中父窗口即是框架窗口,在多文档界面中父窗口为MDI子窗口。一个多文档应用中可以包含多个文档模板,一个模板定义了一个文档和一个或多个视之间的对应关系。同一个文档可以属于多个模板,但一个模板中只允许定义一个文档。同样一个视也可以属于多个文档模板。(不知道我说清楚没有)

接下来看看如何在程序中得到各种对象的指针: 

全局函数AfxGetApp可以得到CWinApp应用类指针 
AfxGetApp()->m_pMainWnd为框架窗口指针 
在框架窗口中:CFrameWnd::GetActiveDocument得到当前活动文档指针 
在框架窗口中:CFrameWnd::GetActiveView得到当前活动视指针 
在视中:CView::GetDocument得到对应的文档指针 
在文档中:CDocument::GetFirstViewPosition,CDocument::GetNextView用来遍历所有和文档关联的视。 
在文档中:CDocument::GetDocTemplate得到文档模板指针 
在多文档界面中:CMDIFrameWnd::MDIGetActive得到当前活动的MDI子窗口 

一般来讲用户输入消息(如菜单选择,鼠标,键盘等)会先发往视,如果视未处理则会发往框架窗口。所以定义消息映射时定义在视中就可以了,如果一个应用同时拥有多个视而当前活动视没有对消息进行处理则消息会发往框架窗口。
 
 
1
 
 
http://www.cnblogs.com/duguguiyu/archive/2007/06/22/792511.html

获得CWinApp

获得CMainFrame

获得CChildFrame

获得CDocument

获得CView

在CWinApp中

AfxGetMainWnd()

m_pMainWnd

AfxGetMainWnd()->MDIGetActive()

AfxGetMainWnd()->GetActiveFrame()

SDI:AfxGetMainWnd()->GetActiveView()->GetDocument()

MDI:AfxGetMainWnd()->MDIGetActive()->GetActiveView()->GetDocument()

SDI:AfxGetMainWnd()->GetActiveView()  
MDI:AfxGetMainWnd()->MDIGetActive()->GetActiveView()
在CMainFrame中

AfxGetApp()

theApp

 

MDIGetActive()

GetActiveFrame()

SDI:GetActiveView()->GetDocument()  
MDI:MDIGetActive()->GetActiveView()->GetDocument()  
SDI:GetActiveView()  
MDI:MDIGetActive()->GetActiveView()
在CChildFrame中

AfxGetApp()

theApp

GetParentFrame()

GetActiveView()->GetDocument()  GetActiveView()
在CDocument中

AfxGetApp()

theApp

AfxGetMainWnd()  

AfxGetMainWnd()->MDIGetActive()

AfxGetMainWnd()->GetActiveFrame()

 POSITION   pos   =   GetFirstViewPosition();GetNextView(pos)  
在CView中

AfxGetApp()

theApp

AfxGetMainWnd()  GetParentFrame()  GetDocument() 
在其他类中

AfxGetApp()

AfxGetMainWnd()  

AfxGetMainWnd()->MDIGetActive()

AfxGetMainWnd()->GetActiveFrame()

SDI:AfxGetMainWnd()->GetActiveView()->GetDocument()

MDI:AfxGetMainWnd()->MDIGetActive()->GetActiveView()->GetDocument()

SDI:AfxGetMainWnd()->GetActiveView()  
MDI:AfxGetMainWnd()->MDIGetActive()->GetActiveView()
理一理MFC的这几个类的关系,可以很容易明白上面的这些乱七八糟的逻辑。
App是应用域,所有的域中的东西都可以通过全局函数访问到它。
MainFrame是主框架,也基本可以用全局函数访问到。
MainFrame下是若干个ChildFrame,ChildFrame中若干个View和Document(可能不成对),ChildFrame管理着View,View和Document进行互操作。
因此整体框架就出来了,一般除了直接应用的关系都可以通过MainFrame-->Active ChildFrame-->Active View-->Document这条线进行访问 _______________________________ http://www.mx68.com/WebDeveloper/2006-03-10/WebDeveloper_29139.shtml

关于MFC下的文档和视图以及框架之间的访问, 这些问题已经是老生常谈了,但我觉得还是都没有详细的说明,特

别是对于英语较差的人,我查看了一些blog,总结了一下!希望对和我一样的人有点帮助! 一:       1:   因为对于SDI程序,主框架窗口就是文档框窗(如果这个也不知道,就要查看一下MFC下的单文档的构成原理了).           下面所说的是关于单文档的.                             例子: 在CMainFrame框架中如何得到视图类的指针.                     可以 先得到框架指针,然后调用 GetActiveView 函数指向当前活动视. C **View * pView;                  pView=(C**View*)((CFrameWnd*)AfxGetApp()->m_pMainWnd)->GetActiveView();

          当然这些也许都知道是这么用的,但真正的m_pMainWnd和AfxGetApp()是什么意思也许有的人不明白.          大家也许都知道如何在App中获得MainFrame刚?框架类): CWinApp 中的 m_pMainWnd变量就是CMainFrame的指针.

   所以在别的类下也可以先得到m_pMainWnd,就得到了MainFrame的指针. 所以得到视图类的指针,必先 得到CFrameWnd的指针m_pMainWnd,然后在调用FrameWnd下的GetActiveView 就指向当前活动视. m_pMainWnd的由来:       每一个MFC应用程序都有一个CWinApp派生类的对象。这个对象对应着程序的主线程。而 CWinApp 类中有一个 CWnd * m_pMainWnd 成员变量。这个成员变量记录了应用程序的主窗口。 当你新建一个MFC应用程序的时候,在 InitInstance虚函数里都会出现对 m_pMainWnd 赋值的语句.唯一的例外是单文档界面的MFC应用程序,你无法在 InitInstance 函数里看到这段代码,因为它已经被隐藏在 ProcessShellCommand 这个函数里了。由此你就可以下结论了:只要创建自己的窗口类,就要把这个类的对象赋值给 m_pMainWnd .而这个成员只能在C**APP类中才可以使用,所以怎样使用这个CWinApp类里的CWnd 类型的变量来得到主框架窗口的指针呢?? AfxGetApp函数才可以 , 因为AfxGetApp()得到的是CWinApp类的对象,且AfxGetApp返回值为CWinApp对象指针,就是MFC生成的C**App.cpp中定义的那个对象(对象theApp的指针)。 因为你是在自己创建的项目中得到CWndApp成员函数或者成员变量,所以你必须强制转换为你自己的项目中的类,才能找到成员函数或者变量. 注: 在单文档中,获得视指针的最简单的方法还是 ((C**View *)CFrameWnd::GetActiveView())                         2:     当然在FrameWnd中也可以得到文档类的指针:                        CMyDocument* pDoc;                        pDoc=(CMyDocument*)((CFrameWnd*)AfxGetApp()->m_pMainWnd)->GetActiveDocument();                    3:     由上面可以知道:在View中怎样获得MainFrame指针 CMainFrame *pMain=(CMainFrame *)AfxGetApp()->m_pMainWnd;

注: 从视图类中获得主帧窗口类指针:用函数:CWnd::GetParentFrame()或AfxGetMainWnd()也 可达到目的。GetParentFrame()的工作原理是在父窗口链中搜索,直到找到CFrameWnd或其派生类为止,并返回其指针。

((CMainFrame *)CWnd::GetParentFrame()) 或者 ((CMainFrame *)AfxGetMainWnd())          二: 当然对于MDI程序,由于子窗口才是文档框窗,因此首先要用GetActiveFrame()取得活动子框架窗口,然后通过该子窗口获取活动视图和文档:

                 CMDIChildWnd* pChild=(CMDIChildWnd*)((CFrameWnd*)AfxGetApp()->m_pMainWnd)-            

        >GetActiveFrame(); 取得活动视图: CMyView* pView=(CMyView*)pChild->GetActiveView();

取得活动文档: CMyDocument* pDoc=pChild->GetActiveDocument();

注: 也可以用这种方法来得到多文档中的视指针 //获得活动子框架窗口 CMDIChildWnd* pChild=(CMDIChildWnd*)GetActiveFrame(); //或: CMDIChildWnd* pChild=MDIGetActive(); //获得活动子帧窗口的活动视图 CMyView* pView=(CMyView*)pChild->GetActiveView();

三: 1.   从视图类获得文档类的指针             在视图类中需要引用文档类的地方之前,使用以下语句: C*Doc *pDoc=(C*Doc*)GetDocument(); 以后便可使用pDoc指针访问文档类。 2.    从文档类取得视图类的指针 CDocument类提供了两个函数用于视图类的定位:

   GetFirstViewPosition()和GetNextView()

注意:GetNextView()括号中的参数用的是引用方式,因此执行后值可能改变.GetFirstViewPosition()用于

返 回第一个视图位置(返回的并非视图类指针,而是一个POSITION类型值),GetNextView()有两个功能:返回下一个视图类的指针以及用引用 调动的方式来改变传入的POSITION类型参数的值。很明显,在Test程序中,只有一个视图类,因此只需将这两个函数调用一次即可得到 CTestView的指针如下(需定义一个POSITION结构变量来辅助操作):

    C*View* pView; POSITION pos=GetFirstViewPosition(); pView=GetNextView(pos);

这 样,便可到了C*View类的指针pView.执行完成几句后,变量pos=NULL,因为没有下一个视图类,自然也没有下一个视图类的 POSITION.但是之几条语句太简单,不具有太强的通用性和安全特征;当象前面说的那样,当要在多个视图为中返回某个指定类的指针时,我们需要遍历所 有视图类,直到找到指定类为止。判断一个类指针指向的是否某个类的实例时,可用IsKindOf()成员函数时行检查.

如: pView->IsKindOf(RUNTIME_CLASS(C*View)); 即可检查pView所指是否是C*View类。 有了以上基础,我们已经可以从文档类取得任何类的指针。为了方便,我们将其作为一个文档类的成员函数,它有一个参数,表示要获得哪个类的指针。实现如下:           CView* C*Doc::GetVieww(CRuntimeClass* pClass) { CView* pView; POSITION pos=GetFirstViewPosition(); while(pos!=NULL){ pView=GetNextView(pos); if(!pView->IsKindOf(pClass)) break;} if(!pView->IsKindOf(pClass)){ AfxMessageBox("Connt Locate the View."); return NULL;} return pView;} 其中用了两次视图类的成员函数IsKindOf()来判断,是因为退出while循环有三种可能: 1.pos为NULL,即已经不存在下一个视图类供操作; 2.pView已符合要求。 3.1和2同是满足。这是因为GetNextView()的功能是将当前视图指针改变成一个视图的位置同时返回当前视图指针,因此pos是pView的下一个视图类的POSITION,完全有可能既是pos==NULL又是pView符合需要。当所需的视图是最后

一个视图是最后一个视图类时就如引。因此需采用两次判断。 使用该函数应遵循如下格式(以取得CTestView指针为例): CTestView* pTestView=(CTestView*)GetView(RUNTIME_CLASS(CTestView)); RUNTIME_CLASS是一个宏,可以简单地理解它的作用:将类的名字转化为CRuntimeClass为指针。 至于强制类型转换也是为了安全特性考虑的,因为从同一个基类之间的指针类型是互相兼容的。这种强制类型转换也许并不必要,但能避免一些可能出现的麻烦

切换视图方法一     CChildFrame * m_×××Frame;//定义     //需初始化m_×××Frame     m_×××Frame = NULL;     if (m_ToolFrame != NULL)     {         m_ToolFrame->MDIActivate();         return;     }//防止重复打开视图     m_×××Frame = new CChildFrame();     CCreateContext context;     context.m_pNewViewClass=RUNTIME_CLASS(C×××View);    if(!m_ToolFrame->LoadFrame(IDR_TOOLMATYPE,WS_MAXIMIZE|WS_OVERLAPPEDWINDOW,this,&context))         return;     m_ToolFrame->ShowWindow(SW_SHOWMAXIMIZED);     m_ToolFrame->InitialUpdateFrame(NULL,true); 切换视图方法二(参照CHKBOOK,MFC,在MSDN里面)    CreateOrActivateFrame( pDocTemplate,        RUNTIME_CLASS(C×××View)); 切换视图方法三(先添加模板)     pDocTemplate->OpenDocumentFile(NULL);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值