1 / 40

使用 MFC

使用 MFC. 在視窗程式的執行過程中 , 使用者與程式 執行間的關係是一個交互影響的過程 . 整個視窗大致可分為兩個部份 , 一是視窗框架 , 二是客戶區. 如何撰寫視窗程式. 利用 AF(Application Frameworks) 簡稱應用軟體架構 因為 AF 本身就是一個很複雜的類別階層 , 而運用 AF 的方法就是利用類別的繼承. CObject. 應用程式類別. 繪圖類別. 容器類別. 其他類別. 視窗類別. 如何撰寫視窗程式. 應用程式類別 : 定義了建立應用程式可能需要利用的類

jagger
Download Presentation

使用 MFC

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 使用MFC 在視窗程式的執行過程中, 使用者與程式 執行間的關係是一個交互影響的過程. 整個視窗大致可分為兩個部份, 一是視窗框架, 二是客戶區

  2. 如何撰寫視窗程式 利用AF(Application Frameworks)簡稱應用軟體架構 因為AF本身就是一個很複雜的類別階層, 而運用AF的方法就是利用類別的繼承 CObject 應用程式類別 繪圖類別 容器類別 其他類別 視窗類別

  3. 如何撰寫視窗程式 應用程式類別: 定義了建立應用程式可能需要利用的類 別, 如:CWinApp(視窗應用程式類別), CDocTemplate(文件範本類別)等等. 視窗程式類別: 定義了建構視窗所需的類別如:CFrameWnd(視窗框架類別),CDialog(對話盒類別), CView(瀏覽類別)等等. 繪圖類別: 用於畫圖的類別, 如:CDC(裝置內文類別), Cpen(畫筆類別),Cbrush(畫刷類別)等等. 容器類別: Clist,Carry,Cmap等容器類別. 其他類別: ODBC資料庫類別.

  4. 如何撰寫視窗程式 要使用MFC類別時,必需要先載入afcwin的標頭檔 當我們要撰寫視窗程式時必需要建立兩種物件 一是繼承CWinApp的應用程式物件 二是繼承CFrameWnd的視窗框架物件

  5. 如何撰寫視窗程式 每一個程式都只有一個應用程式類別(CWinApp), 這個應用程式類別用於產生應用程式物件, 且是程式的進入點. 當建立了應用程式物件後, 將由該物件負責視窗框架物件的建立, 且應用程式類別將有一個屬性指向所使用的視窗框架物件. 應用程式物件 Pointer 視窗框架物件

  6. MFC的Example #include <afxwin.h> //載入afxwin標頭檔 class MyApp : public CWinApp //繼承CWinApp { public: BOOL InitInstance() //程式進入點 { CFrameWnd *Frame = new CFrameWnd(); //建立CFrameWnd物件(產生) m_pMainWnd = Frame; //將m_pMainWnd設定為Frame Frame->Create(NULL,“Hello MFC”); //建立視窗(建立) Frame->ShowWindow(SW_SHOW); return true; } }; MyApp a_app; //建立應用程式物件

  7. 程式說明 要如何自定應用程式類別??? • 繼承CWinApp類別 • 重載CWinApp::IninInstance函數, 此函數為視窗程式的進入點, 回傳值的型態為BOOL class MyApp : public CWinApp //繼承CWinApp { public: BOOL InitInstance() //程式進入點 {…} };

  8. 程式說明 CWinApp::m_pMainWnd屬性, 這個屬性將指向應用程 式所使用的視窗框架物件. CWinApp::IninInstance函數, 在該函數中完成下列工作. • 產生視窗框架物件 • 將該視窗框架物件的指標,設定給CWinApp::m_pMainWnd屬性 • 在螢幕中建立視窗框架 • 顯示視窗框架物件

  9. 程式說明 BOOL InitInstance() //程式進入點 { CFrameWnd *Frame = new CFrameWnd(); //建立CFrameWnd物件 m_pMainWnd = Frame; //將m_pMainWnd設定為Frame Frame->Create(NULL,"Hello MFC"); //建立視窗 Frame->ShowWindow(SW_SHOW); return true;} 建立應用程式物件 MyApp a_app; //建立應用程式物件

  10. 建立自訂視窗 當您想要建立一個自定的視窗框架時, 您必須建立一個繼承於CFrameWnd類別的視窗框架類別, 然後將視窗組合出自定的視窗類別. 在此範例我們不直接利用CFrameWnd類別, 而是使用繼承的方式, 由CFrameWnd類別衍生出自定的MyFrame類別.

  11. MyFrame程式範例 #include <afxwin.h> #include "MyFrame.h" //由資源編輯器所產生的標頭檔 class MyFrame : public CFrameWnd //繼承CFrameWnd類別 { private: CMenu *FMenu; public: MyFrame() { Create(NULL,"Hello MFC"); //建立視窗 FMenu = new CMenu; //產生選單 FMenu->LoadMenu(IDR_MENU1); //載入選單 SetMenu(FMenu); //設定視窗所使用的選單 } }; class MyApp : public CWinApp { public: BOOL InitInstance() { CFrameWnd *Frame = new MyFrame; //產生視窗 m_pMainWnd = Frame; //將視窗物件設定給應用程式 Frame->ShowWindow(SW_SHOW); //顯示視窗 return true; } }; MyApp a_app; //建立應用程式物件

  12. MyFrame程式範例 class MyApp : public CWinApp { public: BOOL InitInstance() { CFrameWnd *Frame = new MyFrame; //產生視窗 m_pMainWnd = Frame; //將視窗物件設定給應用程式 Frame->ShowWindow(SW_SHOW); //顯示視窗 return true; } }; MyApp a_app; //建立應用程式物件

  13. 資源檔的設定與使用 • 在VC++中的File選New, 再點選Files中的Resource Template進行script的編輯. • 再點選Insert中的Resource進行資源檔的編輯. • 編輯完畢後, 再將script存成*.rc的檔案格式, 再到Resource Files中將剛才存檔的.rc import進來即可.

  14. 程式說明 我們將利用MyFrame程式範例介紹下列重點 • 視窗框架與資源檔 • 視窗元件的使用

  15. 程式說明 在上述程式中在MyFrame類別中, 亦有一個指向Cmenu物件的FMenu指標屬性,當您要操作該選單時(如: 新增, 刪除等等)可透過CMenu來完成. 而在第17行利用LoadMenu將定義在資源檔中的選單代號載入, 再利用SetMenu函數將Fmneu設定為視窗使用的選單

  16. 程式說明 在視窗框架類別中是負責產生應用程式物件所使用的視窗框架物件, 也就是應用程式的視窗介面, 所以資源檔中定義的資源大部份都是建立視窗框架時所用的元件 #include "MyFrame.h" //由資源編輯器所產生的標頭檔

  17. 程式說明 // Used by MyFrame.rc #define IDR_MENU1 101 #define ID_Exit 40001 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 102 #define _APS_NEXT_COMMAND_VALUE 40002 #define _APS_NEXT_CONTROL_VALUE 1000 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif

  18. 視窗的訊息傳遞與處理 在視窗作業系統下, 作業系統將不斷由電腦系統的週邊裝置得到訊息, 就連您輕輕的移動了一下滑鼠, 作業系統也會收到滑鼠移動的訊息. 在多而繁雜的訊息中, 如何讓應用程式知道究竟哪些訊息要回應? 要如何回應呢? 這要透過訊息映射表的建立.

  19. 視窗訊息的種類 回應訊息與處理函數分為兩種 • 標準系統訊息 標準系統訊息是由作業系統所產生的訊息, 比如: 移動滑鼠或按下滑鼠左鍵…等. 而接收並處理這類標準系統訊息的類別, 必須衍生自CWnd類別. 定義的方式通常以ON_WM_XXX方式定義 BEGIN_MESSAGE_MAP(類別名稱,基礎類別名稱) ON_WM_LBUTTONDOWN() ON_WM_MOUSEMOVE() ON_WM_LBUTTONUP() END_MESSAGE_MAP()

  20. 視窗訊息的種類 而回應系統訊息名稱, MFC均已定義, 其宣告方式如下 afx_msg void OnLButtonDown(UINT nFlags, CPoint point) {……; }//當滑鼠左鍵按下後的回應函數,取得滑鼠訊息接收權 其中nFlags與point為傳入函數的參數.

  21. 視窗訊息的種類 • 命令訊息 命令訊息大致上是指由使用者自行定義的選單.工具列. 控制項…等視窗元件, 被選取時所產生的訊息. 回應這類訊息的類別必須衍生自CCmdTarget類別. 這類訊息回息回應項目的定義方式如下: BEGIN_MESSAGE_MAP類別名稱,基礎類別名稱) ON_COMMAND(訊息代號,回應函數) … END_MESSAGE_MAP()

  22. 視窗訊息的種類 命令訊息必須在建立該命令時, 即建立一個代號, 這個代號, 就是建立資源物件時設定的資源代號, 比如: 我們在定義File選單的Exit選項為ID_EXIT1. 而回應函數的名稱也必須由我們定義,比如: 我們在定義File選單的Exit函數名稱為ONExit. 而在宣告這類訊息處理函數時, 我們必須在該函數前加afx_msg, 定義方式如下: afx_msg void 回應函數名稱(參數…) ex:afx_msg void OnExit() //ID_EXIT1的回應函數 對於一些大部份視窗程式常用到的命令, MFC亦定義了代號(Standard Command Ids)

  23. 訊息映射表的建立 DECLARE_MESSAGE_MAP() //宣告訊息映射表 然後在類別外宣告所處理的訊息, 以及處理函數. BEGIN_MESSAGE_MAP(MyFrame, CFrameWnd) //建立MyFrame類別的訊息映射表 訊息回應項目 … END_MESSAGE_MAP()

  24. 訊息映射表的建立 class MyFrame : public CFrameWnd { … DECLARE_MESSAGE_MAP()//宣告訊息映表 }; BEGIN_MESSAGE_MAP(MyFrame, CFrameWnd) //建立MyFrame類別的訊息映射表 ON_COMMAND(ID_Exit1, OnExit) ON_WM_LBUTTONDOWN() ON_WM_MOUSEMOVE() ON_WM_LBUTTONUP() END_MESSAGE_MAP() 函數名稱 訊息代號

  25. Mouse訊息傳入的參數 Mouse訊息產生時,幾個特殊按鍵利用nFlags傳入,而 Mouse的座標則經由point傳入

  26. 繪圖相關說明 • SetCapture(); //當滑鼠左鍵按下後的回應函數,取得滑鼠訊息接收權 • CClientDC aDC(this); //建立一個畫布 aDC.SetPixel(point, RGB(255, 0 ,0));//利用SetPixel在畫布上點出紅點 • GetCapture() //判斷滑鼠游標是否在視窗之上 • ReleaseCapture() //當滑鼠左鍵放開後的回應函數,釋放滑鼠訊息接收權

  27. #include <afxwin.h> #include "Message.h" //載入資源檔所使用之標頭檔 class MyFrame : public CFrameWnd { private: CMenu *FMenu; public: MyFrame() //建構子 { Create(NULL,"Hello MFC"); FMenu = new CMenu; FMenu>LoadMenu(IDR_MENU1); SetMenu(FMenu); } ~MyFrame(){ delete FMenu;} //解構子 afx_msg void OnExit() //ID_EXIT1的回應函數 { MessageBox("Exit1"); DestroyWindow(); } afx_msg void OnLButtonDown(UINT nFlags, CPoint point) { SetCapture(); } //當滑鼠左鍵按下後的回應函數,取得滑鼠訊息接收權 afx_msg void OnLButtonUp(UINT nFlags, CPoint point) { ReleaseCapture(); } //當滑鼠左鍵放開後的回應函數,釋放滑鼠訊息接收權 Message程式範例

  28. afx_msg void OnMouseMove(UINT nFlags, CPoint point) { //當滑鼠移動時的回應函數 if (this == GetCapture())//判 斷滑鼠游標是否在視窗之上 {CClientDC aDC(this); //建立一個畫布 aDC.SetPixel(point, RGB(255, 0 ,0));//利用SetPixel在畫布上點出紅點} } afx_msg void OnLButtonUp(UINT nFlags, CPoint point) { ReleaseCapture(); } //當滑鼠左鍵放開後的回應函數,釋放滑鼠訊息接收權 DECLARE_MESSAGE_MAP() //宣告訊息映射表}; class MyApp : public CWinApp //應用程式類別 { public: BOOL InitInstance() //程式進入點 { CFrameWnd *Frame = new MyFrame; m_pMainWnd = Frame; Frame>ShowWindow(SW_SHOW); //顯示視窗 return true; } } a_app; //宣告應用程式物件 Message程式範例

  29. Document/View的基本架構 Document/view(文件/瀏覽)的架構, 就是用來管理視窗介面下, 資料的儲存與顯示, 在分工上, Document物件用於管理視窗程式的資料儲存, 而View物件負責將Document儲存的資料正確顯示在視窗上. 一個完整的視窗應用程式, 必須具備有應用程式類別(CWinApp).視窗框架類別(CFrameWnd).Document類別(文件類別).View類別(瀏覽類別).

  30. Document/View的基本架構 視窗框架物件 應用程式物件 Document物件 View物件

  31. 重新整理 • 應用程式物件用於建立應用程式 • 視窗框架物件用於建立視窗介面 • Document物件用於運作.儲存資料 • View物件用於將Document物件顯示於視窗 • 從資料的角度來看, Document物件與View物件其實是一體的, 只是將資料的處理與顯示的工作分開

  32. 應用程式物件 Pointer 文件樣版物件物件 文件物件 Pointer Pointer 瀏覽物件 Pointer Document/View架構圖 1.產生 指向 視窗框架物件 3.產生 2.產生 Pointer 4.產生

  33. #include <afxwin.h> #include "Doc_View.h" class MyDocument : public CDocument {DECLARE_DYNCREATE(MyDocument) //宣告run-time類別}; IMPLEMENT_DYNCREATE(MyDocument, CDocument) //宣告MyDocument為run-time類別 class MyView : public CView {public: void OnDraw(CDC * aDC) //必須過載的虛擬函數 { } DECLARE_DYNCREATE(MyView)//宣告run-time類別}; IMPLEMENT_DYNCREATE(MyView, CView) //宣告MyView為run-time類別 class MyFrame : public CFrameWnd { DECLARE_DYNCREATE(MyFrame) //宣告run-time類別 }; IMPLEMENT_DYNCREATE(MyFrame, CFrameWnd) //宣告MyFrame為run-time類別 Document/View程式範例

  34. class MyApp : public CWinApp {public: BOOL InitInstance() {CDocument *doc; //宣告指向文件的指標 CSingleDocTemplate* DocTemplate; //宣告指向單文件樣版物件的指標 DocTemplate = new CSingleDocTemplate( //建立具有單文件樣版物件 IDR_MENU1, //用於單文件框架的資源代號 RUNTIME_CLASS(MyDocument), //單文件視窗的Document RUNTIME_CLASS(MyFrame), //單文件視窗的視窗框架 RUNTIME_CLASS(MyView)); //單文件視窗的View AddDocTemplate(DocTemplate);//將單文件樣版物件設定給MyApp doc = DocTemplate->CreateNewDocument(); //建立新的文件 m_pMainWnd = DocTemplate->CreateNewFrame( doc, NULL ); //建立一個視窗框架 DocTemplate->InitialUpdateFrame ( (CFrameWnd*)m_pMainWnd, doc );//起始化視窗框架中的View m_pMainWnd->ShowWindow ( SW_SHOW); //顯示視窗 return true;}} a_app;//建立應用程式物件 Document/View程式範例

  35. 程式說明 宣告Run-Time類別 因為CSignleDocument在無法得知視窗框架物件.Vie w類別.Document類別的情況下,等到執行時才決定運用哪幾個類別的應用程式. 宣告 DECLARE_DYNAMIC(類別名稱) 然後在該類別外做如下宣告 IMPLEMENT_DYNAMIC(類別名稱,衍生類別名稱)

  36. #include <afxwin.h> #include "repaint.h" #include <afxtempl.h> //定義樣版類別的標頭檔 class MyDocument : public CDocument { public: CArray<CPoint, CPoint &> pArray; //容納滑鼠軌跡點的Array容器 void AddPoint(CPoint p) //將軌跡點加到容器內 { pArray.Add(p); } CPoint GetPoint(int i) //將軌跡點從容器中取出 { return pArray[i]; } int GetSize() { return pArray.GetSize(); } //取得容器的大小 DECLARE_DYNCREATE(MyDocument) //宣告為run-time類別 DECLARE_MESSAGE_MAP() //宣告訊息映射表 }; IMPLEMENT_DYNCREATE(MyDocument, CDocument) //建立run-time類別 BEGIN_MESSAGE_MAP(MyDocument, CDocument) END_MESSAGE_MAP() //建立訊息映射表 Document/View架構的應用視窗的重繪

  37. class MyView : public CView {public: void OnDraw(CDC * aDC) //過載OnDraw虛擬函數 {MyDocument *doc = (MyDocument *)GetDocument(); //取得目前Document物件的指標 int num = doc->GetSize(); //取得目前儲存的軌跡點點數 int i; for(i = 0; i < num; ++i) //將Document中儲存的軌跡點重繪到視窗上 {CPoint point = doc->GetPoint(i); aDC->SetPixel(point, RGB(255, 0 ,0)); }} afx_msg void OnLButtonDown(UINT, CPoint point) { SetCapture(); } //取得滑鼠訊息的接收權 afx_msg void OnMouseMove(UINT, CPoint point) {if (this == GetCapture()) {CClientDC aDC(this);//建立畫布 aDC.SetPixel(point, RGB(255, 0 ,0)); //將點畫在畫布上 MyDocument *doc = (MyDocument *)GetDocument();//取得目前Document物件的指標 doc->AddPoint(point); //將軌跡點加入Document物件中 }} Document/View架構的應用視窗的重繪

  38. afx_msg void OnLButtonUp(UINT, CPoint point){ ReleaseCapture(); } //釋放滑鼠訊息的接收權 DECLARE_DYNCREATE(MyView) //宣告為run-time類別 DECLARE_MESSAGE_MAP() //宣告訊息映射表}; IMPLEMENT_DYNCREATE(MyView, CView)//建立run-time類別 BEGIN_MESSAGE_MAP(MyView, CView) ON_WM_LBUTTONDOWN() ON_WM_MOUSEMOVE() ON_WM_LBUTTONUP() END_MESSAGE_MAP() //建立訊息映射表 class MyFrame : public CFrameWnd { public: DECLARE_DYNCREATE(MyFrame) //宣告為run-time類別 DECLARE_MESSAGE_MAP() //宣告訊息映射表 }; IMPLEMENT_DYNCREATE(MyFrame, CFrameWnd) //建立run-time類別 BEGIN_MESSAGE_MAP(MyFrame, CFrameWnd) END_MESSAGE_MAP() //建立訊息映射表 Document/View架構的應用視窗的重繪

  39. class MyApp : public CWinApp {public: BOOL InitInstance() {CDocument *doc; CSingleDocTemplate* DocTemplate; DocTemplate = new CSingleDocTemplate( //單文件樣版類別 IDR_MENU1, RUNTIME_CLASS(MyDocument), RUNTIME_CLASS(MyFrame), RUNTIME_CLASS(MyView)); AddDocTemplate(DocTemplate);//將文件樣版物件加入應用程式 doc = DocTemplate->CreateNewDocument(); //建立新文件 m_pMainWnd = DocTemplate->CreateNewFrame( doc, NULL ); //建立新的視窗框架 DocTemplate->InitialUpdateFrame ( (CFrameWnd*)m_pMainWnd, doc ); //起始化View物件 m_pMainWnd->ShowWindow ( SW_SHOW ); //顯示視窗 return true; } } a_app; Document/View架構的應用視窗的重繪

  40. 程式說明 • 利用MFC所提供的容器類別 Carray類別, 將滑鼠在視窗中移動時, 傳入的軌跡點存起來. • Carray的宣告方式: Carray<儲存的資料型別,讀取儲存資料的傳回值> 函數說明 • void AddPoint(Cpoint p)//將軌跡點加入容器中. • Cpoint GetPoint(int i)//從容器中取得軌跡點. • Int GetSize()//取得軌跡點的大小.

More Related