MFC MDI程式獲得當前使用中視窗的視類指標

來源:互聯網
上載者:User

1.從視圖類獲得文檔類的指標

如前所述,在視圖類中需要引用文檔類的地方之前,使用以下語句:
CTextDoc*pDoc=(CTestDoc*)GetDocument();
以後便可使用pDoc指標訪問文檔類。
此處的強制類型轉換在Test應用程式中並不必需,因為該程式中只有一個視圖類,並且在Initstance()中用SDI文件範本進行了裝配,你可以在Test.cpp中的Initstance()方法中看到以下語句:
CSingleDocTemplate*pDocTemplate;
pDocTemplate=newCSingleDocTemplate(IDR_MAINFRAME,RUNTIME_CLASS(CTestDoc),RUNTIME_CLASS(CMainFrame),
RUNTIME_CLASS(CTestView));
AddDocTemplate(pDocTemplate);
以及TestView.h中的線上定義:
inlineCTestDoc*CTestView::GetDocument()
{return(CTestDoc*)m_pDocument;}
簡而言之,就是說CTestView的GetDocument()函數自然而然地認為CTestDoc是與它“相配”的,當產生了一個具有多個視圖類的應用程式時(如用CSplitterWnd)將視窗分為兩欄,但這兩欄並非從同一種視圖類派生就屬於這種情況。具體實現在本文討論範圍之外),只有一個視圖類能與唯一的文檔類用文件範本進行裝配,那麼在另外一個未經裝配的類中要取得文檔類的指標,則需時行強制類型轉換。

2.從文檔類取得視圖類的指標

CDocument類提供了兩個函數用於視圖類的定位:GetFirstViewPosition()和GetNextView(),具體文法如下:
virtualPOSITIONGetFirstViewPosition()const;
virtualCView*GetNextView(POSITION&rPosition)const;
注意:GetNextView()括弧中的參數用的是引用方式,因此執行後值可能改變。
GetFirstViewPosition()用於返回第一個視圖位置(返回的並非視圖類指標,而是一個POSITION類型值),GetNextView()有兩個功能:返回下一個視圖類的指標以及用引用調動的方式來改變傳入的POSITION型別參數的值。很明顯,在Test程式中,只有一個視圖類,因此只需將這兩個函數調用一次即可得到CTestView的指標如下(需定義一個POSITION結構變數來輔助操作):
CTestView*pTestView;
POSITIONpos=GetFirstViewPosition();
pTestView=GetNextView(pos);
這樣,便可到了CTestView類的指標pTestView.執行完成幾句後,變數pos=NULL,因為沒有下一個視圖類,自然也沒有下一個視圖類的POSITION.

但是之幾條語句太簡單,不具有太強的通用性和安全特徵;當象前面說的那樣,當要在多個視圖為中返回某個指定類的指標時,我們需要遍曆所有視圖類,直到找到指定類為止。判斷一個類指標指向的是否某個類的執行個體時,可用IsKindOf()成員函數時行檢查,如:
pView->IsKindOf(RUNTIME_CLASS(CTestView));
即可檢查pView所指是否是CTestView類。
有了以上基礎,我們已經可以從文檔類取得任何類的指標。為了方便,我們將其作為一個文檔類的成員函數,它有一個參數,表示要獲得哪個類的指標。實現如下:
CView*CTestDoc::GetVieww(CRuntimeClass*pClass)
{CView*pView;
POSITIONpos=GetFirstViewPosition();
while(pos!=NULL)
{
pView=GetNextView(pos);
if(pView->IsKindOf(pClass))
break;
}
if(!pView->IsKindOf(pClass))
returnNULL;
returnpView;}
其中用了兩次視圖類的成員函數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為指標。
至於強制類型轉換也是為了安全特性考慮的,因為從同一個基類之間的指標類型是互相相容的。這種強制類型轉換也許並不必要,但能避免一些可能出現的麻煩。

3.從一個視圖類取得另一視圖類的指標

綜合1和2,很容易得出視圖類之間互相獲得指標的方法:就是用文檔類作中轉,先用1的方法得到文檔類的指標,再用2的方法,以文檔類的視圖定位函數取得另一個視圖類。同樣,可以實現成一個函數:
(假設要從CTestAView中取得指向其它視圖類的指標)
CView*CTestAView::GetView(CRuntimeClass*pClass)
{CTestDoc*pDoc=(CTestDoc*)GetDocument();
CView*pView;
POSITIONpos=pDoc->GetFirstViewPosition();
while(pos!=NULL)
{
pView=pDoc->GetNextView(pos);
if(pView->IsKindOf(pClass))
break;
}
if(!pView->IsKindOf(pClass))
returnNULL;
returnpView;}
這個函數和2中的GetView()相比,一是多了第一句以取得文檔類指標,二是在GetFirstViewPosition()和GetNextView()前加上了文檔類指標,以表示它們是文檔類成員函數。
有了此函數;當要從CTestAView中取得CTestBView的指標時,只需如下:
CTestBView*pTestbView=(CTestView*)GetView(RUNTIME_CLASS(CTestBView));

4.從主幀視窗類別獲得視圖類指標

對本文所舉的Test這各SDI程式來說,這是簡單的,只需用CFrameWnd類的GetActiveView()成員函數即可。格式如下:
CFrameWnd::GetActiveView()
但將此函數應用在MDI應用的CMDIFrameWnd為中時,並不象所想的那樣獲得當前活動子視窗的視圖類,而是返回NULL,這是一個要領性問題。在MDI程式中,CMDIFrameWnd沒有和任何視圖類發生關係,也就是說沒有視圖類直接屬於它,只有子幀視窗類別CMDIChildWnd才是所有子視窗視圖類的父視窗。而子幀視窗的父視窗才是CFrameWnd。因此,在MDI程式中獲得即時檢視類的正確方法應為:先獲得活動子幀視窗,再從活動子幀視窗中獲得即時檢視類:
//獲得活動子幀視窗
CMDIChildWnd*pChild=(CMDIChildWnd*)GetActiveFrame();
//或:CMDIChildWnd*pChild=MDIGetActive();
//獲得活動子幀視窗的即時檢視
CMyView*pView=(CMyView*)pChild->GetActiveView();

5.從視圖類中獲得主幀視窗類別指標:

用函數:CWnd::GetParentFrame()或AfxGetMainWnd();
可達到目的。GetParentFrame()的工作原理是在父視窗鏈中搜尋,直到找到CFrameWnd或其衍生類別為止,並返回其指標。用法在InfoViewer中有詳細介紹。

6.在任何類中獲得應用程式類
用MFC全域函數AfxGetApp()可做到。

7.從應用程式類中獲得主幀視窗類別
CWinThread類有一個資料成員叫m_pMainWnd,由於CWinApp類由CWinThread派生而來,我們的應用程式為又由CWinApp派生而來,所以我們的CTestApp類也有一個m_pMainWnd成員,它所指南的即是CMainFrame類。(需進行合適的強制類型轉換)。

總結起來有幾點注意:
A.在類A中獲得類B的指標時,類A應包含類B的標頭檔。
B.在很多時候要進行強制類型轉換,並要注意括弧的括法。
由於衍生類別和父類指標類型的相容,使明確區分各個類變得十分重要。在拿不準的時候,最好加上強制類型轉換。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.