Visual C++ Windows Programming 第三章 MFC簡介 台大電機系 李奇錚
大綱 MFC介紹 MFC 的基本架構 MFC 的使用方式 資源的設計與使用 訊息處理 Document / View 的觀念
MFC介紹 AF( application frameworks) 由軟體廠商所提供 撰寫應用軟體的架構 AF與物件導向 軟體再用的觀念 繼承和聚合 MFC Microsoft Foundation Class MFC是一個AF Program reuse
八大類別 CObject 和視覺相關的 CFrameWnd , CDialog , CView 和應用程式相關的 Serialization : 將物件儲存到檔案,或自檔案讀出 Diagnostic output : 提供programmer在執行時診斷物件 ASSERT_VALID , AssertVaild , Dump , afxDump , TRACE Run-Time Class Info : 提供programmer在執行時其判斷物件型別 IsKindOf or RUNTIME_CLASS 和視覺相關的 CFrameWnd , CDialog , CView 和應用程式相關的 CWinApp , CFrameWnd , CDocument 這些都繼承自CCmdTarget OLE2 製作OLE Server的類別
八大類別 Internet服務類別 CFileFind , CInternetSession ,CHttp ,Connection 資料庫相關 CDataBase , CRecordSet 一般用途的類別 CString , CTime ,CPoint,.. Internet伺服器 CHtmlStream , CHttpServer
MFC 的基本架構 CObject 應用程式類別 容器類別 繪圖類別 視窗類別 資料庫類別 網際網路服務類別
全域函數 全域變數 : 不屬於任何類別,可以隨時隨地被呼叫 Afxbort – 終止程式的執行 AfxBeginThread – 啟動新的執行緒 AfxEndThread – 結束執行緒 AfxGetApp – 取得CWinApp物件的指標 AfxThrowFileException – 產生File的例外
MFC 的使用方式 標頭檔 應用程式物件與視窗框架物件 #include <afxwin.h> CWinApp CFrameWnd
應用程式物件與視窗框架物件 應用程式物件 指向 m_pMainWnd 視窗框架物件 產生
撰寫程式 借用MFC的類別 直接使用 直接使用已經寫好的類別 繼承 繼承原有的類別,針對不同的特性,加以修改
MFC 的使用方式 (續) #include <afxwin.h> class CFirstApp : public CWinApp { public: BOOL InitInstance() { CFrameWnd *Frame = new CFrameWnd(); m_pMainWnd = Frame; Frame->Create(NULL, "Hello, MFC!!"); Frame->ShowWindow(SW_SHOW); return true; } } ; CFirstApp a_app;
自訂視窗框架及資源檔 利用繼承的方式 繼承CFrameWnd,已產生符合需求的Frame 自行定義所需求的資源檔
資源的設計與使用 Resource Script Accelerator Bitmap Cursor Dialog Icon Menu String Table Toolbar Version
資源的設計與使用 (續) Menu Item 屬性 ID: 按下 menu item 傳回的 command 代號 Caption: menu item 的文字 ("&" : 快速鍵) Seperator: 分隔線 Checked: menu item 是否被選取 Pop-up: menu "folder" or menu item Grayed: 是否為 enabled Inactive: 是否正為游標選取中
資源的設計與使用 (續) #include <afxwin.h> #include "resource.h" class CFirstFrame : public CFrameWnd { private: CMenu *FMenu; public: CFirstFrame() { Create(NULL, "Menu Resource Demo"); FMenu = new CMenu; FMenu->LoadMenu(IDR_MENU1); SetMenu(FMenu); } } ; class CFirstApp : public CWinApp { BOOL InitInstance() { CFrameWnd *Frame = new CFirstFrame; m_pMainWnd = Frame; //Frame->Create(NULL, "Hello, MFC!!"); Frame->ShowWindow(SW_SHOW); return true; CFirstApp a_app;
訊息(Message) 利用MFC撰寫視窗程式,是利用Message Map的方式來回應訊息的 訊息的種類 負責回應訊息的類別中,宣告訊息應對 DECLARE_MESSAGE_MAP() 訊息的種類 標準系統訊息 由作業系統所產生的,ex.滑鼠左鍵被按下,移動滑鼠.. 由CWnd家族的類別負責接收處理 ON_WM_XXX 命令訊息 大多是使用者自訂的選單,工具列等被選取時,所發出的訊息 由CCmdTarget家族類別負責處理和接收 ON_COMMAND(訊息代號,回應函數)
標準系統訊息 Message Map BEGIN_MESSAGE_MAP(…. , …..) ON_WM_MOUSEMOVE() ……… END_MESSAGE_MAP() 處理函式 afx_msg void OnMouseMove(UNIT nFlags , CPoint point) { ….. }
命令訊息 Message Map BEGIN_MESSAGE_MA(訊息代碼 , 回應函數) ON_COMMAND() ……… END_MESSAGE_MAP() Ex. ON_COMMAND(ID_Exit1,OnExit) 處理函式 afx_msg void 回應函數名稱() { ….. } Ex . afx_msg void OnExit() {…………..}
訊息處理 DECLARE_MESSAGE_MAP() BEGIN_MESSAGE_MAP(class, base) END_MESSAGE_MAP()
訊息處理 (續) class CFirstFrame : public CFrameWnd { ...; DECLARE_MESSAGE_MAP() } ; ... BEGIN_MESSAGE_MAP(CFirstFrame, CFrameWnd) ON_COMMAND(ID_EXIT, OnExit) ON_WM_LBUTTONDOWN() ON_WM_MOUSEMOVE() ON_WM_LBUTTONUP() END_MESSAGE_MAP()
訊息處理 (續) #include <afxwin.h> #include "resource.h" class CFirstFrame : public CFrameWnd { private: CMenu *FMenu; public: CFirstFrame() { Create(NULL, "Message Processing Demo"); FMenu = new CMenu; FMenu->LoadMenu(IDR_MENU1); SetMenu(FMenu); } ~CFirstFrame() { delete FMenu; } afx_msg void OnExit() { MessageBox("It's time to stop.", "Stop Window", MB_ICONSTOP); DestroyWindow(); afx_msg void OnLButtonDown(UINT nFlags, CPoint point) { SetCapture(); } afx_msg void OnMouseMove(UINT nFlags, CPoint point) { if(this == GetCapture()) { CClientDC aDC(this); aDC.Ellipse(point.x - 3, point.y - 3, point.x + 3, point.y + 3);
訊息處理 (續) afx_msg void OnLButtonUp(UINT nFlags, CPoint point) { ReleaseCapture(); } DECLARE_MESSAGE_MAP() } ; BEGIN_MESSAGE_MAP(CFirstFrame, CFrameWnd) ON_COMMAND(ID_EXIT, OnExit) ON_WM_LBUTTONDOWN() ON_WM_MOUSEMOVE() ON_WM_LBUTTONUP() END_MESSAGE_MAP() class CFirstApp : public CWinApp { public: BOOL InitInstance() { CFrameWnd *Frame = new CFirstFrame; m_pMainWnd = Frame; Frame->ShowWindow(SW_SHOW); return true; } CFirstApp a_app;
Document / View ch3_2的程式有一些問題 視窗的重繪?? 因為沒有將視窗的資料記錄下來!! Document / View MFC所提供的一種資料處理和顯示的機制
Document / View Document CDocumnet 和應用程式互動的那些資料 包含Serialize()這個函式 不單單只是文字,可以是遊戲資料,幾何模型,文字檔… 包含Serialize()這個函式 可以進行資料的存取 Void CxxDoc : Serialize(CArchive &ar) { if(ar.IsStoring()) ….. } else
Document / View View 顯示Document的方式 設定一個Document應該如何顯示視窗上 ex. 全部顯示或部份顯示
Document / View Document Windows Frame View
Document / View How MFC Link Document and View Using Document Templates Document Templates 每一個Document都有自己的document template 有兩種以上的Doc , 只需要一個document template來管理即可 兩種類型 SDI : CSingleDocTemplate MDI : CMultiDocTemplate
Document / View Application Object Doc template Doc Object Frame Window View Object 表示產生
Document / View #include <afxwin.h> #include "resource.h" #include <afxtempl.h> class MyDocument : public CDocument { public: CArray <CPoint, CPoint &> pArray; MyDocument() { SetTitle("Document / View Demo"); } void AddPoint(CPoint p) { pArray.Add(p); } CPoint GetPoint(int i) { return pArray[i]; } int GetSize() { return pArray.GetSize(); } DECLARE_DYNCREATE(MyDocument) DECLARE_MESSAGE_MAP() } ; IMPLEMENT_DYNCREATE(MyDocument, CDocument) BEGIN_MESSAGE_MAP(MyDocument, CDocument) END_MESSAGE_MAP()
class MyView : public CView { void OnDraw(CDC *aDC) { MyDocument *doc = (MyDocument *) GetDocument(); int num = doc->GetSize(); int i; for(i = 0; i < num; i++) { CPoint point = doc->GetPoint(i); aDC->Ellipse(point.x - 3, point.y - 3, point.x + 3, point.y + 3); } afx_msg void OnLButtonDown(UINT, CPoint point) { SetCapture(); } afx_msg void OnMouseMove(UINT, CPoint point) { if (this == GetCapture()) { CClientDC aDC(this); aDC.Ellipse(point.x - 3, point.y - 3, point.x + 3, point.y + 3); doc->AddPoint(point); afx_msg void OnLButtonUp(UINT, CPoint point) { ReleaseCapture(); } DECLARE_DYNCREATE(MyView) DECLARE_MESSAGE_MAP() } ;
IMPLEMENT_DYNCREATE(MyView, CView) BEGIN_MESSAGE_MAP(MyView, CView) ON_WM_LBUTTONDOWN() ON_WM_MOUSEMOVE() ON_WM_LBUTTONUP() END_MESSAGE_MAP() class MyFrame : public CFrameWnd { public: afx_msg void OnExit() { MessageBox("It's time to stop.", "Stop Window", MB_ICONSTOP); DestroyWindow(); } DECLARE_DYNCREATE(MyFrame) DECLARE_MESSAGE_MAP() } ; IMPLEMENT_DYNCREATE(MyFrame, CFrameWnd) BEGIN_MESSAGE_MAP(MyFrame, CFrameWnd) ON_COMMAND(ID_EXIT, OnExit)
class MyApp : public CWinApp { 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); m_pMainWnd->ShowWindow(SW_SHOW); return true; } } ; MyApp a_app;
補充 InitialUpdateFrame() DECLARE_DYNCREATE(CObject-derived) Calling this function causes the views in that frame window to receive their OnInitialUpdate calls DECLARE_DYNCREATE(CObject-derived) Enables objects of CObject-derived classes to be created dynamically at run time. IMPLEMENT_DYNCREATE must be included in the class implementation
補充 Collection : 由CObject衍伸出來 Ex. CArray , CList CArray<ObjectType , ObjectType &>anArray Ex. CArray<CPoint,CPoint &>PointArray PointArray.Add(aPoint) aPoint = PointArray.GetAt(2); PointArray.SetAt(3,aPoint); or PointArray[3] = aPoint