MFC各种视图指针的获取

  
 
网页加载中 ......
标题 MFC 获得各种视图指针的方法
类别 网络编程
日期 070821
长度 6258 Bytes [Copy to clipboard]
获得各种视图指针如下
1) View 中获得 Doc 指针
2) App 中获得 MainFrame 指针
3) View 中获得 MainFrame 指针
4) 获得 View (已建立)指针
5) 获得当前文档指针
6) 获得状态栏与工具栏指针
7) 获得状态栏与工具栏变量
8) Mainframe 获得菜单指针
9) 在任何类中获得应用程序类
10) 从文档类取得视图类的指针 (1)
11) App 中获得文档模板指针
12) 从文档模板获得文档类指针
13) 在文档类中获得文档模板指针
14) 从文档类取得视图类的指针 (2)
15) 从一个视图类取得另一视图类的指针
16) 获取分割视图中各个视图的指针

VC 中编程对于刚刚开始学习的同学,最大的障碍和问题就是消息机制和指针获取与操作。其实这些内容基本上是每本 VC 学习工具书上必讲的内容,而且通过 MSDN 很多问题都能解决。 下面文字主要是个人在编程中指针使用的一些体会,说的不当的地方请指正。

一般我们使用的框架是 VC 提供的 Wizard 生成的 MFC App Wizard(exe) 框架,无论是多文档还是单文档,都存在指针获取和操作问题。 下面这节内容主要是一般的框架,然后再讲多线程中的指针使用。使用到的类需要包含响应的头文件。

首先一般获得本类 ( 视,文档,对话框都支持 ) 实例指针 this ,用 this 的目的,主要可以通过类中的函数向其他类或者函数中发指针,以便于在非本类中操作和使用本类中的功能。

1 View 中获得 Doc 指针
CYouSDIDoc *pDoc=GetDocument() // 一个视只能有一个文档。
2) App 中获得 MainFrame 指针
CWinApp 中的 m_pMainWnd 变量就是 MainFrame 的指针 也可以:

CMainFrame *pMain =(CMainFrame *)AfxGetMainWnd();

4) 获得 View (已建立)指针
CMainFrame *pMain=(CmaimFrame *)AfxGetApp()- > m_pMainWnd;

CyouView *pView=(CyouView *)pMain- > GetActiveView();


5) 获得当前文档指针
CDocument * pCurrentDoc =(CFrameWnd *)m_pMainWnd- > GetActiveDocument();

6) 获得状态栏与工具栏指针
CStatusBar * pStatusBar (CStatusBar *)AfxGetMainWnd()- > GetDescendantWindow(AFX_IDW_STATUS_BAR);

CToolBar * pToolBar=(CtoolBar *)AfxGetMainWnd()- > GetDescendantWindow(AFX_IDW_TOOLBAR);

7) 如果框架中加入工具栏和状态栏变量还可以这样
(CMainFrame *)GetParent()- > m_wndToolBar; (CMainFrame *)GetParent()- > m_wndStatusBar;

8) Mainframe 获得菜单指针
CMenu *pMenu=m_pMainWnd- > GetMenu();

9) 在任何类中获得应用程序类用 MFC 全局函数 AfxGetApp() 获得。

10) 从文档获得视图类指针目的一般为了控制同一文档的多个视图的定位问题,我的体会特别是文字处理 CEditView 当产生多个视图类时,这个功能是非常需要的。

CDocument 类提供了两个函数用于视图类的定位: GetFirstViewPosition() GetNextView()

virtual POSITION GetFirstViewPosition() const; virtual CView* GetNextView(POSITION & rPosition) const;        

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

CTestView* pTestView;

POSITION pos=GetFirstViewPosition();

pTestView=GetNextView(pos);

这样,便可到了 CTestView 类的指针 pTestView. 执行完几句后,变量 pos=NULL, 因为没有下一个视图类,自然也没有下一个视图类的 POSITION. 但是这几条语句太简单,不具有太强的通用性和安全特征;当象前面说的那样,当要在多个视图为中返回某个指定类的指针时,我们需要遍历所有视图类,直到找到指定类为止。判断一个类指针指向的是否某个类的实例时,可用 IsKindOf() 成员函数时行检查,如: pView- > IsKindOf(RUNTIME_CLASS(CTestView)); 即可检查 pView 所指是否是 CTestView 类。 有了以上基础,我们已经可以从文档类取得任何类的指针。为了方便,我们将其作为一个文档类的成员函数,它有一个参数,表示要获得哪个类的指针。

实现如下:

CView* CTestDoc::GetView(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./r/n http://www.VCKBASE.com"); return NULL; } return pView; }

其中用了两次视图类的成员

函数 IsKindOf() 来判断,是因为退出 while 循环有三种可能:

1.pos NULL ,即已经不存在下一个视图类供操作;

2.pView 已符合要求。

1 2 同是满足。这是因为 GetNextView() 的功能是将当前视图指针改变成一个视图的位置同时返回当前视图指针,因此 pos pView 的下一个视图类的 POSITION, 完全有可能既是 pos==NULL 又是 pView 符合需要。当所需的视图是最后一个视图是最后一个视图类时就如引。因此需采用两次判断。 使用该函数应遵循如下格式(以取得 CTestView 指针为例):

CTestView* pTestView=(CTestView*)GetView(RUNTIME_CLASS(CTestView));

RUNTIME_CLASS 是一个宏,可以简单地理解它的作用:将类的名字转化为 CRuntimeClass 为指针。 至于强制类型转换也是为了安全特性考虑的,因为从同一个基类之间的指针类型是互相兼容的。这种强制类型转换也许并不必要,但能避免一些可能出现的麻烦。

3. 从一个视图类取得另一视图类的指针 综合 1 2 ,很容易得出视图类之间互相获得指针的方法:就是用文档类作中转,先用 1 的方法得到文档类的指针,再用 2 的方法,以文档类的视图定位函数取得另一个视图类。同样,可以实现成一个函数: (假设要从 CTestA V i ew 中取得指向其它视图类的指针)

CView* CTestA V i ew::GetView(CRuntimeClass* pClass) {

CTestDoc* pDoc=(CTestDoc*)GetDocument();

CView* pView; POSITION pos=pDoc- > GetFirstViewPosition();

while(pos!=NULL)

{

     pView=pDoc- > GetNextView(pos);

    if(!pView- > IsKindOf(pClass)) break;

}

if(!pView- > IsKindOf(pClass))

{

AfxMessageBox("Connt Locate the View.");

return NULL;

}

return pView;

}

这个函数和 2 中的 GetView() 相比,一是多了第一句以取得文档类指针,二是在 GetFirstViewPosition() GetNextView() 前加上了文档类指针,以表示它们是文档类成员函数。 有了此函数;当要从 CTestA V i ew 中取得 CTestBView 的指针时,只需如下: CTestBView* pTestbView=(CTestView*)GetView(RUNTIME_CLASS(CTestBView));

11 )对于单文档中也可以加入多个文档模板,但是一般的开发就使用 MDI 方式开发多文档模板,其方法与上述视图的获取方法很接近,这里稍做解释,如果不清楚,请查阅 MSDN ,(以下四个内容( 11 12 13 14 )来源: http://sanjianxia.myrice.com/vc/vc45.htm 可以用 CWinApp::GetFirstDocTemplatePostion 获得应用程序注册的第一个文档模板的位置; 利用该值来调用 CWinApp::GetNextDocTemplate 函数,获得第一个 CDocTemplate 对象指针。 POSITION GetFirstDocTemplate( ) const; CDocTemplate *GetNextDocTemplate( POSITION & pos ) const; 第二个函数返回由 pos 标识的文档模板。 POSITION MFC 定义的一个用于迭代或对象指针检索的值。通过这两个函数,应用程序可以遍历整个文档模板列表。如果被检索的文档模板是模板列表中的最后一个,则 pos 参数被置为 NULL

12 )一个文档模板可以有多个文档,每个文档模板都保留并维护了一个所有对应文档的指针列表。 CDocTemplate::GetFirstDocPosition 函数获得与文档模板相关的文档集合中第一个文档的位置,并用 POSITION 值作为 CDocTemplate::GetNextDoc 的参数来重复遍历与模板相关的文档列表。函数原形为: viaual POSITION GetFirstDocPosition( ) const = 0; visual CDocument *GetNextDoc(POSITION & rPos) const = 0; 如果列表为空,则 rPos 被置为 NULL.

13 )在文档中可以调用 CDocument::GetDocTemplate 获得指向该文档模板的指针。函数原形如下: CDocTemplate * GetDocTemplate ( ) const; 如果该文档不属于文档模板管理,则返回值为 NULL

14) 一个文档可以有多个视。每一个文档都保留并维护一个所有相关视的列表。 CDocument::AddView 将一个视连接到文档上,将该视加入到文档相联系的视的列表中,并将视的文档指针指向该文档。当有 File/New File/Open Windows/New Window/Split 的命令而将一个新创建的视的对象连接到文档上时, MFC 会自动调用该函数,框架通过文档 / 视的结构将文档和视联系起来。当然,程序员也可以根据自己的需要调用该函数。 Virtual POSITION GetFirstViewPosition( ) const; Virtual CView * GetNextView( POSITION & rPosition) cosnt; 应用程序可以调用 CDocument::GetFirstViewPosition 返回与调用文档相联系的视的列表中的第一个视的位置,并调用 CDocument::GetNextView 返回指定位置的视,并将 rPositon 的值置为列表中下一个视的 POSITION 值。如果找到的视为列表中的最后一个视,则将 rPosition 置为 NULL.

15) 从一个视图类取得另一视图类的指针 这个应用在多视的应用程序中很多见,一般如果自己在主程序或者主框架中做好变量记号,也可以获得,还有比较通用的就是用文档类作中转,以文档类的视图遍历定位,取得另一个视图类。这个功能从本文第 10 项中可以得到。

16) 获取分割视图中各个视图的指针

CSplitterWnd m_wndSplitter

m_wndSplitter.CreateStatic(this, 1, 2) // 分割成一行两列

m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CLeftPaneView), CSize(10 10), pContext)

m_wndSplitter.CreateView(0, 1, RUNTIME_CLASS(CRightPaneFrame), CSize(0, 0), pContext) // 获取左边视图的两种方法

CLeftPaneView* pLeftPaneView = (CLeftPaneView*) m_wndSplitter.GetPane(0,0); // 上一句可以用下句代替: //

CLeftPaneView* pLeftPaneView = (CLeftPaneView *)GetActiveView(); // 获取右边视图

pLeftPaneView- > m_pRightPaneFrame = (CRightPaneFrame*) m_wndSplitter.GetPane(0,1);

View 中获得 MainFrame 指针
CMainFrame *pMain=(CmaimFrame *)AfxGetApp()- > m_pMainWnd; or ((CMainFrame *)GetParent())- >
 

你可能感兴趣的:(MFC各种视图指针的获取)