VC 程式設計對初學者最大的障礙是訊息機制與指標取得操作。這些內容幾乎是每本 VC 入門書必講的,透過 MSDN 也能解決大部分問題。以下分享個人在程式設計中指標使用的體會,錯誤處請指正。
一般使用 Wizard 產生的 MFC App Wizard (exe) 架構,無論單一或多文件,都存在指標取得與操作問題。使用到的類別需包含對應標頭檔。首先取得本類別(視圖、文件、對話方塊皆支援)實例指標 this,目的在於透過類別函數將指標傳遞給其他類別或函數,方便在非本類別中操作本類別功能。
CYouSDIDoc *pDoc = GetDocument();(一個視圖對應一個文件)CWinApp 的 m_pMainWnd 即為 MainFrame 指標,或 CMainFrame *pMain = (CMainFrame *)AfxGetMainWnd();CMainFrame *pMain = (CMainFrame *)AfxGetApp()->m_pMainWnd;CMainFrame *pMain = (CMainFrame *)AfxGetApp()->m_pMainWnd;
CYouView *pView = (CYouView *)pMain->GetActiveView();
CDocument *pCurrentDoc = (CFrameWnd *)m_pMainWnd->GetActiveDocument();CStatusBar *pStatusBar = (CStatusBar *)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_STATUS_BAR);
CToolBar *pToolBar = (CToolBar *)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_TOOLBAR);
(CMainFrame *)GetParent()->m_wndToolBar;
(CMainFrame *)GetParent()->m_wndStatusBar;
CMenu *pMenu = m_pMainWnd->GetMenu();AfxGetApp()目的通常為控制同一文件多個視圖的定位問題(特別是文字處理 CEditView 產生多視圖時)。CDocument 提供兩個函數:
virtual POSITION GetFirstViewPosition() const;
virtual CView* GetNextView(POSITION& rPosition) const;
注意:GetNextView() 參數用引用,執行後值會改變。GetFirstViewPosition() 傳回第一個視圖位置(POSITION 型別),GetNextView() 雙重功能:傳回下一個視圖指標,並透過引用改變傳入的 POSITION 參數值。
範例(需定義 POSITION 變數輔助):
CTestView* pTestView;
POSITION pos = GetFirstViewPosition();
pTestView = GetNextView(pos);
執行後 pos = NULL(無下一視圖)。但此寫法通用性與安全性不足。當需在多視圖中傳回指定類別指標時,需遍歷所有視圖直到找到為止。判斷指標是否指向某類別實例,可用 IsKindOf():
pView->IsKindOf(RUNTIME_CLASS(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 https://www.VCKBASE.com");
return NULL;
}
return pView;
}
使用方式:CTestView* pTestView = (CTestView*)GetView(RUNTIME_CLASS(CTestView));。RUNTIME_CLASS 宏將類別名稱轉為 CRuntimeClass 指標。強制型別轉換為安全考量。
綜合以上,以文件類別作中介:先取得文件指標,再用文件的視圖定位函數取得另一視圖。同樣可封裝為函數:
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;
}
使用:CTestBView* pTestBView = (CTestView*)GetView(RUNTIME_CLASS(CTestBView));
單一文件也可加入多文件模板,但通常用 MDI 開發。方法與視圖取得類似:
CWinApp::GetFirstDocTemplatePosition() 取得第一個文件模板位置CWinApp::GetNextDocTemplate() 取得 CDocTemplate 指標CDocTemplate::GetFirstDocPosition() / GetNextDoc() 遍歷文件CDocument::GetDocTemplate() 取得文件模板指標CDocument::GetFirstViewPosition() / GetNextView() 遍歷視圖本文內容多來自網路與 MSDN,整理旨在讓大家不用再搜尋,列出標題方便操作。