1. 程式人生 > >孫鑫VC學習筆記:第八講 逃跑按鈕的巧妙實現和MFC中指標的獲取

孫鑫VC學習筆記:第八講 逃跑按鈕的巧妙實現和MFC中指標的獲取



MFC應用程式中指標的使用
   1) 在View中獲得Doc指標 CYouSDIDoc *pDoc=GetDocument();一個視只能有一個文件。
   2) 在App中獲得MainFrame指標
   CWinApp 中的 m_pMainWnd變數就是MainFrame的指標也可以: CMainFrame *pMain =(CMainFrame *)AfxGetMainWnd();
   3) 在View中獲得MainFrame指標 CMainFrame *pMain=(CmaimFrame *)AfxGetApp()->m_pMainWnd;
   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) 從文件類取得檢視類的指標

   我是從http://download.cqcnc.com/soft/program/article/vc/vc405.html學到的,從文件獲得檢視類指標目的一般為了控制同一文件的多個檢視的定位問題,我的體會特別是文書處理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的方法,以文件類的檢視定位函式取得另一個檢視類。同樣,可以實現成一個函式:
   (假設要從CTestAView中取得指向其它檢視類的指標)
   CView* CTestAView::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()前加上了文件類指標,以表示它們是文件類成員函式。有了此函式;當要從CTestAView中取得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項中可以得到。
   
  
   _______________________________________________________________
  
   訪問應用程式的其它類
  
   獲得CWinApp:
   -在CMainFrame,CChildFrame,CDocument,CView中直接呼叫AfxGetApp()或用theApp
   -在其它類中只能用AfxGetApp()
  
   獲得CMainFrame:
   -在CMinApp中用AfxGetMainWnd()或者m_pMainWnd
   -在CChildFrame中可用GetParentFrame()
   -在其它類中用AfxGetMainWnd()
  
   獲得CChildFrame:
   -在CView中用GetParentFrame()
   -在CMainFrame中用MDIGetActive()或GetActiveFrame()
   -在其它類中用AfxGetMainWnd()->MDIGetActive()或AfxGetMainWnd()->GetActiveFrame()
  
   獲得CDocument:
   -在CView中用GetDocument()
   -在CChildFrame中用GetActiveView()->GetDocument()
   -在CMainFrame中用
   -if SDI:GetActiveView()->GetDocument()
   -if MDI:MDIGetActive()->GetActiveView()->GetDocument()
   -在其它類中
   -if SDI:AfxGetMainWnd()->GetActiveView()->GetDocument()
   -if MDI:AfxGetMainWnd()->MDIGetActive()->GetActiveView()->GetDocument()
  
   獲得CView:
   -在CDocument中 POSITION pos = GetFirstViewPosition();GetNextView(pos)
   -在CChildFrame中 GetActiveView()
   -在CMainFrame中
   -if SDI:GetActiveView()
   -if MDI:MDIGetActive()->GetActiveView()
   -在其它類中
   -if SDI:AfxGetMainWnd()->GetActiveView()
   -if MDI:AfxGetMainWnd()->MDIGetActive()->GetActiveView()
  
  另一篇參考文章。來源:http://yuelinniao.spaces.live.com/blog/cns!588F0F46185E082D!135.entry
   
  訪問應用程式的其它類
  
  獲得CWinApp:
   -在CMainFrame,CChildFrame,CDocument,CView中直接呼叫AfxGetApp()或用theApp
   -在其它類中只能用AfxGetApp()
  
  獲得CMainFrame:
   -在CMinApp中用AfxGetMainWnd()或者m_pMainWnd
   -在CChildFrame中可用GetParentFrame()
   -在其它類中用AfxGetMainWnd()
  
  獲得CChildFrame:
   -在CView中用GetParentFrame()
   -在CMainFrame中用MDIGetActive()或GetActiveFrame()
   -在其它類中用AfxGetMainWnd()->MDIGetActive()或AfxGetMainWnd()->GetActiveFrame()
  
  獲得CDocument:
   -在CView中用GetDocument()
   -在CChildFrame中用GetActiveView()->GetDocument()
   -在CMainFrame中用
   -if SDI:GetActiveView()->GetDocument()
   -if MDI:MDIGetActive()->GetActiveView()->GetDocument()
   -在其它類中
   -if SDI:AfxGetMainWnd()->GetActiveView()->GetDocument()
   -if MDI:AfxGetMainWnd()->MDIGetActive()->GetActiveView()->GetDocument()
  
  獲得CView:
   -在CDocument中 POSITION pos = GetFirstViewPosition();GetNextView(pos)
   -在CChildFrame中 GetActiveView()
   -在CMainFrame中
   -if SDI:GetActiveView()
   -if MDI:MDIGetActive()->GetActiveView()
   -在其它類中
   -if SDI:AfxGetMainWnd()->GetActiveView()
   -if MDI:AfxGetMainWnd()->MDIGetActive()->GetActiveView()
  
  
  不過要注意在doc中要取得view的指標CView*要注意類CView*宣告的問題,
  因為預設情況下,mfc在View.h中已經包含了Doc.h,如果在Doc.h中包含View.h,就會引起巢狀包含問題,這樣要在Doc.h中加入 class CView; 而在CDoc.cpp中加入 #include "View.h"
  
  //////////////////////////////////////////////////////////////////
  其實完全可以在CYourApp中新增各種視或文件的指標,在那些視或文件初始化的時候將指標傳給CYourApp中的對應變數,這樣以後不管在哪用上面指標只需(CYourApp*)AfxGetApp()取其屬性變數即可,明瞭而且清楚更是方便我一直專門操作的說:)
  
  //////////////////////////////////////////////////////////////////
  我先拋塊磚,有玉的砸過來!
  在何時何地,你都可以通過以下方法精確的得到任何一個物件(Application,DocTemplate,Document,View,Frame)
  1。通過AfxGetApp()得到當前的App物件;
  2。通過AfxGetMainWnd()得到主視窗;
  3。通過CMDIFrameWnd::GetActiveFrame得到當前活動視窗;
  4。通過GetNextWindow()遍例所有的子視窗;(如果要得到你想要的子視窗,可以通過特定的成員變數來標);
  5。通過CWinApp::GetFirstDocTemplatePostion()以及CWinApp::GetNextDocTemplate() 的組合應用來遍歷所有的DocTemplate物件,並且用CDocTemplate::GetDocString()來判斷當前得到的文件莫板物件是哪個。
  6。通過CDocTemplate::GetFirstDocPosition()以及CDocTemplate的GetNextDoc()組合來遍歷所有的該模板的文件物件,並用CDocument::GetDocTemplate()來得到文件模板,用CDocment::GetTitle() 或者GetPathName()來判斷當前的文件是哪個。
  7。通過CDocuemt的GetFirstViewPositon()以及GetNextView()來遍歷檢視物件,一般通過訪問View的成員變數來區別各個檢視;通過CView::GetDocument()來得到文件物件;
  8。Frame->View: 通過GetActiveView方法;
  9。Frame->Doc:通過GetActiveDocument();
  10。View->Frame:GetParentFrame();
  11。View->Doc:GetDocuemt()//前面已經說了。
  12。Doc->View:前面說了;
  13。Doc->Frame:不知道有沒有很直接的方法