學習了一段時間MFC了,原來總是模仿別人的程式做。不知其所以然,後面發現這些問題必須要解決。始終不可能迷迷糊糊的過關,於是乎在網上對一些函數進行了尋找,並且結合之間的理解整理一下。主要是整理整理之間的思路。
一、CFileDialog
參考:http://blog.sina.com.cn/s/blog_4618b1720100edq8.html
1:構造
CFileDialog是常用的開啟圖形的對話方塊類,其一般的建構函式形式如下:
CFileDialog( BOOL bOpenFileDialog, LPCTSTRlpszDefExt = NULL, LPCTSTRlpszFileName = NULL, DWORDdwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, LPCTSTRlpszFilter = NULL,
CWnd*pParentWnd = NULL );
在這裡說明一下一些參數的含義:
第一個bOpenFileDialog為True時為開啟對話方塊,為false為儲存對話方塊。
第二個lpszDefExt 是預設的尾碼,lpszFileName 是預設的檔案名稱字,這兩個可以構成預設的開啟和儲存對象。當然其分開組合會更加多樣化。
第三個dwFlags 這個是很重要的一個參數,其可以設定是開啟文檔的各種方式,其中最常用的就是選擇多文檔還是單文檔。
第四個lpszFilter 這個也是重要的一個參數,其表示要過濾的開啟文檔。
第五個pParentWnd 不常用,預設為NULL。
2:修改
對於建立好了的CFlieDialog可以通過m_ofn結構體進行修改。其有一個很重要的參數lpstrFile,這個參數是用於儲存Dialog本身以外的一些緩衝資訊。因為CFileDialog的內建檔案快取長度只有200,所以設定一個檔案快取來保證緩衝的有效性(注意:必須先初始化為0)。其他常用的還有nMaxFile等等,這些可以通過VAssitX提示得到。
3:應用
CFileDialog定義了很多有用的函數,這些都可以通過VAssitX提示得到。注意在這裡面他自己定義的或者說是常用的是通過加粗黑體表示的。
其中常用的函數有:
CString CFileDialog::GetPathName( ) 得到完整的檔案名稱,包括目錄名和副檔名如:c:\test\test1.txt
CString CFileDialog::GetFileName( ) 得到完整的檔案名稱,包括副檔名如:test1.txt
CString CFileDialog::GetExtName( ) 得到完整的副檔名,如:txt
CString CFileDialog::GetFileTitle ( ) 得到完整的檔案名稱,不包括目錄名和副檔名如:test1
POSITION CFileDialog::GetStartPosition( ) 對於選擇了多個檔案的情況得到第一個檔案位置。
CString CFileDialog::GetNextPathName( POSITION& pos ) 對於選擇了多個檔案的情況得到下一個檔案位置,並同時返回當前檔案名稱。但必須已經調用過POSITION CFileDialog::GetStartPosition( )來得到最初的POSITION變數。
注意:其中GetStartPosition()和GetNextPathName()是必須在dwFlags選擇多文檔的時候才可以進行。他們的含義是得到選擇的第一個和下一個文檔的位置,如果是單文檔就沒有GetNextPathName()這一說了。
二、MFC中幾個類之間的關係
參考:http://www.vckbase.com/index.php/wv/459
1:大關係
第一App類和CMainFrame類是第一級的,下面的CChildFrame類是第二級的, Doc類和View類是第三級的。但是App類不是和其他幾個類一個系統的,他是用於整體管理的老大。第一級和第三級之間的上向下的聯絡必須通過第二級,而上向就不用,因為使用的是全域函數。
1) View類和Doc類
a:View類中獲得Doc類
CYouSDIDoc *pDoc=GetDocument();一個視只能有一個文檔。
注注意:這裡預設的是當前即時檢視調用GetDocument,如果架構中有多個視圖,可以通過選擇視圖來調用GetDocument函數,總之這裡其實是View類的成員函數,這裡理解類和對象的關係十分重要。
b:Doc類中獲得View類
CDocument類提供了兩個函數用於視圖類的定位:GetFirstViewPosition()和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\nhttp://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為指標。
至於強制類型轉換也是為了安全特性考慮的,因為從同一個基類之間的指標類型是互相相容的。這種強制類型轉換也許並不必要,但能避免一些可能出現的麻煩。
c:View類獲得View類
從一個視圖類取得另一視圖類的指標 綜合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));
2):View類和MainFrame類
a:View獲得MainFrame
這裡是下級獲得上級,一般只能藉助全域函數。這裡用CMainFrame *pMain=(CmaimFrame *)AfxGetApp()->m_pMainWnd;
或者CMainFrame *pMain =(CMainFrame *)AfxGetMainWnd();
b:在MainFrame中獲得View
這裡是上級獲得下級,可以用上級本身的函數就可以了。這裡是用m_pMainWnd。
CMainFrame* pMain=(CmaimFrame *)AfxGetApp()->m_pMainWnd;//獲得第一級
CMDIChildWnd* pChild=pMainFrame->MDIGetActive();//獲得第二級
CyouView *pView=(CyouView *)pChild->GetActiveView();//獲得第三級
3):Doc類和MainFrame類
a:Doc類中獲得MainFrame類
同理,直接只能用全域函數。這裡CMainFrame *pMain=(CmaimFrame *)AfxGetApp()->m_pMainWnd;
CMainFrame *pMain =(CMainFrame *)AfxGetMainWnd();
b:MainFrame類中獲得Doc類
CDocument * pCurrentDoc =(CFrameWnd *)m_pMainWnd->MDIGetActive()->GetActiveDocument();
4):獲得應用程式
用MFC全域函數AfxGetApp()獲得