MFC分析對話框的運行機制心得體會_第1頁
MFC分析對話框的運行機制心得體會_第2頁
MFC分析對話框的運行機制心得體會_第3頁
MFC分析對話框的運行機制心得體會_第4頁
MFC分析對話框的運行機制心得體會_第5頁
已閱讀5頁,還剩37頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

VC++MFC屬性表對話框的運行機制2012-07-0119:09屬性表對話框的初始化包括框架對話框的初始化和頁的初始化。頁的初始化工作可在OnInitDialog函數中進行,而框架對話框的初始化應該在OnCreate函數中完成。根據CPropertySheet::DoModal返回的是IDOK還是IDCANCEL,程序可以判斷出關閉對話框時按的是OK還是Cancel按鈕,如果屬性表對話框是模態對話框,在其底部會有3個按鈕,依次為OK>Cancel和Apply(應用)按鈕,如果對話框是非模態的,則沒有這些按鈕。OK與Cancel按鈕的意義與普通按鈕沒什么兩樣,Apply按鈕則是屬性表對話框所特有的。普通的模態對話框只有在用戶按下了OK按鈕返回后,對話框的設置才能生效,而設計Apply的意圖是讓用戶能在不關閉對話框的情況下使對話框的設置立即生效。由此可見,Apply按鈕的作用是使用戶在設置完數據后,不必退出對話框,就可以反復進行設置,這在許多應用場合下是很有用的。為了對上述3個按鈕作出響應,CPropertyPage類提供了OnOK,OnCancel和OnApply函數,用戶可覆蓋這3個函數以完成所需的工作。需要指出的是這3個函數并不是直接響應按鈕的BN_CLICKED消息的,但在按鈕按下后它們是被間接調用。這些函數的說明如下:1VirtualvoidOnOK():在按下OK或Apply按鈕后,該函數被調用。默認的OnOK函數幾乎什么也不干,像數據交換和關閉對話框這樣的工作是在別的地方完成的,這與2.VirtualvoidOnCancel():在按下Cancel按鈕后,該函數將被調用。默認的OnCancel函數也是幾乎什么也不干;3.VirtualBOOLOnApply():在按下OK或Apply按鈕后,該函數將被調用。默認的OnApply會調用OnOK函數。函數的返回值如果是TRUE,則對話框中的設置將生效,否則無效。令人不解的是,MFC并未考慮CPropertySheet類的按鈕響應問題,不要指望能通過ClassWizard來自動創建按鈕的BN_CLICKED消息處理函數,通常的按鈕響應都是在CPropertyPage類完成的。下面幾個CPropertyPage類的成員函數也與屬性表的運行機制相關。VoidSetModified(BOOLbChanged=TRUE):該函數用來設置修改標志。若參數bChanged為True,則表明對話框中的設置已改動,否則說明設置未改動。該函數的一個主要用途是允許或禁止Apply按鈕。在默認情況下,Apply按鈕是禁止的。只要一調用SetModfed(TRUE),Apply按鈕就被允許,而調用SetModfied(FALSE)并不一定能使Apply按鈕禁止,只有在所有被標為改動的頁都調用了SetModified(FALSE)后,Apply按鈕才會被禁止。另外,該函數對OnApply的調用也有影響,當Apply按鈕被按下后,只有那些被標記為改動過的頁的OnApply函數才會被調用。在調用該函數之前,程序需要叛斷頁中的內容是否已被修改,可通通過處理諸如BN_CLICKED、EN_CHANGE這樣的控件消息來感知頁的內容的改變;1.1MFC文檔視圖結構程序結構總攬當我們使用MFCAppWizard生成一個MFC程序,選用所有默認的設置(當然也是MultipleDocuments,本文討論主要基于MultipleDocuments,對于SingleDocument情況僅以簡單表述提及,皆因后者和前者很多相似相同之處,但前者更為復雜,并且更加常用。,假設你的程序名稱為A,則你會得到CMainFrame、CChildFrame、CAboutDlg、CADoc、CAView、CAApp6個類(SingleDocument僅少一個CChildFrame類,其余均同)。這些類的具體含義將在后面給出,這里先要給出一個MFC支持文檔視圖結構程序(以下簡稱App)的主要組成:—個App(對應類CAApp)可以包含多個文檔模版(CDocTemplate),但是MFCAppWizard(無論是SDI還是MDI)都只是默認生成一個。但是在實際開發中一個文檔模版不夠,需要自己手工添加(在后面實際項目例子提供示例)。這個結構是通過MFC中CWinApp的成員變量CDocManager*m_pDocManager實現的,我們的CAApp正是繼承自MFC提供的CWinApp類。CDocManager類則擁有一個指針鏈表CPtrListm_templateList來維護這些文檔模版。這些文檔模版都是在CAApp::InitInstanceAddDocTemplate(pDocTemplate)。CDocTemplate擁有3個成員變量,分別保存著Document、View、Frame的CRuntimeClass指針,另外持有成員變量m_nIDResource,用來指定這個Document顯示時候采用的菜單資源。這4份數據都在CAApp::InitInstance()中CDocTemplate的構造函數中指定。在Document中擁有一個回指CDocTemplate的指針(m_pDocTemplate)。一個文檔可以有多個視圖,由 Document中成員變量CPtrListm_ViewList維護。CFrameWnd擁有一個成員變量CView*m_pActiveView指向當前活動的View。CView中擁有一個成員變量CDocument*m_pDocument指向該視圖相關的Document。[注解]:①MFCSDI/MDI程序默認都默認生成了一個文檔模版,并將這個文檔模版Add到其文檔模版的鏈表中,由于這是MFC默認提供的,因此這個文檔模版會被插入到文檔模版的第一個位置,而MFC也是通過這個文檔模版的特定位置可以確定的。默認情況下,當我們點擊File(Open)/File(New)的時候,這個文檔模版會被啟用。除了侯捷先生在《深入淺出MFC中列出的以上的深入分析,我們還應該(很大程度上更加重要)掌握以下的關于MFCSDI/MDI的知識:文檔的本質:文檔是用來保存數據以及關于數據的處理的,每當MFCSDI/MDI響應File(Open)/File(New)的時候都會打開一份文檔。文檔可以擁有多個視圖。文檔和視圖的關系可以這樣理解:文檔是被視圖觀察的對象。視圖本質:視圖在Windows中就是一^窗口,也就是一個可視化的矩形區域。視圖是用來表示文檔的數據的。但是每個視圖必需依附于一個框架(SDI中是MainFrame,MDI是ChildFrame)。當然你可以自己去Create一個視圖,并且去顯示它。框架的本質:框架實際是也是一個Windows窗口。但是在框架上可以放置菜單、工具欄、狀態欄等。而視圖則放在框架的客戶區。因此MFC中我們看到的窗口實際上Frame和View共同作用的結果。在某一時刻,程序中只有一個活動的文檔、框架和視圖,即當前的文檔、框架、視圖。1.2MFCSDI/MDI各個類之間的互訪在實際項目開發中用的最多就是各個類之間的互訪問,這里將網絡上和書籍中提到的做了一個總結,也是筆者在實際開發中都用到過的。訪問對象訪問位置訪問實現應用程序任何位置①AfxGetAppO;

視圖框架類中GetActiveView();//當前的活動視圖文檔類中GetFirstViewPosition();〃可以獲取全部視圖GetNextView();文檔文檔類中GetDocument();

文當模版類中GetFirstDocPosition();//該文檔模版對應全部文檔GetNextDoc();框架類中GetActiveDocument();//當前活動文當子框架類(MDI中)主框架類中MDIGetActive();GetActiveFrame

();視圖類中GetParentFrame();文檔模版文檔類中GetDocTemplate();應用程序App中GetFirstDocTemplatePosition();GetNextDocTemplate()

■9說明:1)以上給出的都是方法,實際訪問中可能還要進行以下簡單的處理,如類型轉換,循環遍歷等;2)可能沒有列舉完所有可能位置的互訪問,但可以通過他們的組合得到。2文檔、視圖、框架之間的關聯MFCSDI/MDI中的核心就在于文檔、視圖、框架之間的關聯,形成了一個有機的可系,但是在實際的項目開發中很多時候需要動態進行他們的之間的關聯。運作的整體。MFC運作的整體。MFC提供了默認的關聯關2.1文檔和視圖間的關聯使用MFCAppWizard聲稱MFCSDI/MDI程序,在App類的InitInstance()方法中有如下代碼(假設Project名稱均為Test):SDI中CSingleDocTemplate*pDocTemplate;pDocTemplate = newCSingleDocTemplate(IDR_MAINFRAME,RUNTIME_CLASS(CTestDoc),RUNTIME_CLASS(CMainFrame)#mainSDIframewindowRUNTIME_CLASS(CTestView));AddDocTemplate(pDocTemplate);MDI中CMultiDocTemplate*pDocTemplate;pDocTemplate = newCMultiDocTemplate(IDR_TESTTYPE,RUNTIME_CLASS(CTestDoc),RUNTIME_CLASS(CChildFrame),//customMDIchildframeRUNTIME_CLASS(CTestView));AddDocTemplate(pDocTemplate);這里通過CDocTemplate(無論是SDI中的CSingleDocTemplate還是MDI中的CMultiDocTemplate)的構造函數,將文當、視圖和框架(SDI中與主框架,MDI中與自框架)關聯在一起了,形成了一個整體。手工實現文當和視圖的關聯在實際的項目開發時候僅僅依靠MFCAppWizard生成的文當和視圖、框架是不夠的,因此我們需要掌握手工進行這種關聯。手工進行文當和視圖的關聯可以有以下兩種實現方式:模仿MFCAppWizard實現,使用CDocTemplate的構造函數:在上面的分析中我們可以看到通過CDocTemplate(無論是SDI中的CSingleDocTemplate還是MDI中的CMultiDocTemplate)的構造函數我們可以獲得文檔、視圖和框架的關聯。因此可以通過模擬這種方式進行關聯。具體實現方法如下:1)創建新的文檔、視圖和框架類,方法是使用VC中的InsertMFCClass實現。注意到框架類選擇CMDIChildWnd作為基類,文檔類選擇CDocument作為基類,而視圖類則可以根據需要選擇CView或其子類(CEditView)等作為基類。2)為該框架添加菜單資源,方法是在VC資源窗口Menu菜單下添加新的菜單,當然可以通過復制VC提供默認菜單進行修改。3)在App類的InitInstance()中添加如下類似代碼:CMultiDocTemplate*m_pDocTemplate;newm_pDocTemplateCMultiDocTemplate(newIDR_TESTTYPE〃改為你新建的菜單資源IDRUNTIME_CLASS(CTestDoc)j/Z改為你新建的文檔類RUNTIME_CLASS(CChildFrame),//改為你新建的框架類RUNTIME_CLASS(CTestView));//改為你新建的視圖類AddDocTemplate(m_pDocTemplate);

4)為了記錄這個文檔模版,你可以在App類中添加一個CMultiDocTemplate*類型變量來維持這個文檔模版。上面給出了通過CDocTemplate上面給出了通過CDocTemplate的構造函數將文檔、視圖、和框架關聯起來,但是有時候我們并不想創建一個新的文檔模版,我們只是想給同一個數據提供不同的結果顯示,或者說是為同一個文檔添加一個新的視圖,并提供他們之間的一個切換。還有一種可能就是我們本來不是一個文檔視圖結構進行業務邏輯和表示層的一個分離。第一種方法的實現方法:支持的程想為視圖添加一個文檔,更好支持的程想為視圖添加一個文檔,更好Step1:使用VC6.0新建一個Project,命名為:MultiView。除選擇單文檔屬性外,一切使用“默認”方式。于是你可以獲得五個類: CMainFrame,CMultiViewApp,CMultiViewDoc,CMultiViewView,和CAboutDlg;Step2:新建一^新的視圖View,添加一個新的MFCClass(Insert—>NewClass),基類為CView(或者CView的派生子類,如CEditView等)。類的名字為CAnotherView,這就是新的視圖;并為CAnotherView添加GetDocument的實現:CMultiViewDoc*CAnotherView::GetDocument(){return(CMultiViewDoc*)m_pDocument;Step3:在CMultiViewApp添加成員變量記錄這兩個視圖:private:CView*m_pFirstView;

CView*m_pAnotherView;給程序菜單IDR_MAINFRAME添加一個菜單項目“視圖”,該菜單項有兩個子菜單“視圖一”和“視圖二”添加相應函數(voidCMultiViewApp::OnShowFirstview()和 voidCMultiViewApp());CMultiViewApp());::OnShowSecondviewStep4:創建新的視圖:在BOOLCMultiViewApp::InitInstance()中添加代//創建一個新的視圖CView* m_pActiveView((CFrameWnd*)m_pMainWnd)->GetActiveView();m_pFirstView=m_pActiveView;m_pAnotherView=newCAnotherView();H文檔和視圖關聯CDocument* m_pDoc((CFrameWnd*)m_pMainWnd)->GetActiveDocument();CCreateContextcontext;context.m_pCurrentDoc=m_pDoc;//創建視圖UINTm_IDFORANOTHERVIEW=AFX_IDW_PANE_FIRST+1;CRectrect;m_pAnotherView->Create(NULL,NULL,WS_CHILD,rect,m_pMainWnd,m_IDFORANOTHERVIEW9&context);Step5:現在已經創建了視圖,并且都和文檔關聯起來了。現在要作的就是視圖間的轉換。在voidCMultiViewAppOnShowFirstview()中添加實現代碼:OnShowFirstview()中添加實現代碼:voidCMultiViewApp::OnShowFirstview(){//TODO:AddyourcommandhandlercodehereUINT temp=::GetWindowLong(m_pAnotherView->m_hWnd,GWL_ID);::SetWindowLong(m_pAnotherView->m_hWnd,GWL_ID,::GetWindowLong(m_pFirstView->m_hWnd,GWL_ID));::SetWindowLong(m_pFirstView->m_hWnd,GWL_ID,temp);m_pAnotherView->ShowWindow(SW_HIDE);m_pFirstView->ShowWindow(SWJSHOW);((CFrameWnd*)m_pMainWnd)->SetActiveView(m_pFirstView);((CFrameWnd*)m_pMainWnd)->RecalcLayout();m_pFirstView->Invalidate();在 voidCMultiViewApp:OnShowSecondview()中添加實現代碼:voidCMultiViewApp::OnShowSecondview(){//TODO:AddyourcommandhandlercodehereUINT temp=::GetWindowLong(m_pAnotherView->m_hWnd,GWL_ID);::SetWindowLong(m_pAnotherView->m_hWnd,GWL_ID,::GetWindowLong(m_pFirstView->m_hWnd,GWL_ID));::SetWindowLong(m_pFirstView->m_hWnd,GWL_ID,temp);m_pFirstView->ShowWindow(SW_HIDE);m_pAnotherView->ShowWindow(SW_SHOW);((CFrameWnd*)m_pMainWnd)->SetActiveView(m_pAnotherView);((CFrameWnd*)m_pMainWnd)->RecalcLayout();m_pAnotherView->Invalidate();Step6:為了演示,這里將不同的視圖給予一個標記,在CMultiViewView和CAnotherView的OnDraw方法中分別添加以下代碼:pDC->TextOut(40O,3O0,"FirstView");pDC->TextOut(4O0,320,pDoc->GetTitle());pDC->TextOut(400,300,"AnotherView");pDC->TextOut(400,320,pDoc->GetTitle());至此就大功告成了,但是實現過程中有幾點說明:1)實現中由于使用到相關的類,因此在必要的地方要include相關的頭文件,這里省略;CAnotherView的默認構造函數是Protected的,需要將其改為Public,或者提供一個產生CAnotherView對象的方法(因要創建視圖對象);2)這里給出的是一個示例代碼,2)這里給出的是一個示例代碼,實際開發中可以通過參考實現獲得自己想要實現的具體應用情況(例如視圖類的不同、數量不同,更重要的還有業務邏輯的不同實現等);第二種視圖和文檔關聯的方法:我們使用CCreateContext類進行他們之間的關聯,具體實現為:m_pAnotherView=newCAnotherView();//new一個新的視圖,可以改為你新建的視圖//獲取一個已有的文檔,可以是你新建的文檔CDocument* m_pDoc =((CFrameWnd*)m_pMainWnd)->GetActiveDocument。;/文檔和視圖關聯CCreateContextcontext;context.m_pCurrentDoc=m_pDoc;/創建視圖UINTm_IDFORANOTHERVIEW=AFX_IDW_PANE_FIRST+1;〃創建視圖的ID號,你可以自己設置CRectrect;m_pAnotherView->Create(NULL,NULL,WS_CHILD,rect,m_pMainWnd,m_IDFORANOTHERVIEW,&context);在框架和視圖關聯的時候進行設置,具體見一下框架和視圖關聯部分。2.2框架和視圖的關聯在第一部分分析我們知道,框架和視圖其實都是windows窗口,不過框架提供了菜單、標題欄、狀態欄等資源,而視圖則只是一個矩形區域。MFC程序中視圖決定大多數時候要依附于一個框架(SDI中的MainFrame和MDI中的子框架窗口),可以這樣理解,框架相當于一個窗口容器(當然它本身也是一個windows窗口),而視圖則正好是放置在框架內客戶區域的內容

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論