使用
Download
1 / 40

使用 MFC - PowerPoint PPT Presentation


  • 174 Views
  • Uploaded on

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

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about ' 使用 MFC' - jagger


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.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
使用MFC

在視窗程式的執行過程中, 使用者與程式 執行間的關係是一個交互影響的過程.

整個視窗大致可分為兩個部份, 一是視窗框架, 二是客戶區


如何撰寫視窗程式

利用AF(Application Frameworks)簡稱應用軟體架構

因為AF本身就是一個很複雜的類別階層, 而運用AF的方法就是利用類別的繼承

CObject

應用程式類別

繪圖類別

容器類別

其他類別

視窗類別


如何撰寫視窗程式

應用程式類別: 定義了建立應用程式可能需要利用的類

別, 如:CWinApp(視窗應用程式類別), CDocTemplate(文件範本類別)等等.

視窗程式類別: 定義了建構視窗所需的類別如:CFrameWnd(視窗框架類別),CDialog(對話盒類別),

CView(瀏覽類別)等等.

繪圖類別: 用於畫圖的類別, 如:CDC(裝置內文類別),

Cpen(畫筆類別),Cbrush(畫刷類別)等等.

容器類別: Clist,Carry,Cmap等容器類別.

其他類別: ODBC資料庫類別.


如何撰寫視窗程式

要使用MFC類別時,必需要先載入afcwin的標頭檔

當我們要撰寫視窗程式時必需要建立兩種物件

一是繼承CWinApp的應用程式物件

二是繼承CFrameWnd的視窗框架物件


如何撰寫視窗程式

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

應用程式物件

Pointer

視窗框架物件


Mfc example
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; //建立應用程式物件


程式說明

要如何自定應用程式類別???

  • 繼承CWinApp類別

  • 重載CWinApp::IninInstance函數, 此函數為視窗程式的進入點, 回傳值的型態為BOOL

    class MyApp : public CWinApp //繼承CWinApp

    {

    public:

    BOOL InitInstance() //程式進入點

    {…}

    };


程式說明

CWinApp::m_pMainWnd屬性, 這個屬性將指向應用程 式所使用的視窗框架物件.

CWinApp::IninInstance函數, 在該函數中完成下列工作.

  • 產生視窗框架物件

  • 將該視窗框架物件的指標,設定給CWinApp::m_pMainWnd屬性

  • 在螢幕中建立視窗框架

  • 顯示視窗框架物件


程式說明

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; //建立應用程式物件


建立自訂視窗

當您想要建立一個自定的視窗框架時, 您必須建立一個繼承於CFrameWnd類別的視窗框架類別, 然後將視窗組合出自定的視窗類別.

在此範例我們不直接利用CFrameWnd類別, 而是使用繼承的方式, 由CFrameWnd類別衍生出自定的MyFrame類別.


Myframe
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; //建立應用程式物件


Myframe1
MyFrame程式範例

class MyApp : public CWinApp

{

public:

BOOL InitInstance()

{

CFrameWnd *Frame = new MyFrame; //產生視窗

m_pMainWnd = Frame; //將視窗物件設定給應用程式

Frame->ShowWindow(SW_SHOW); //顯示視窗

return true;

}

};

MyApp a_app; //建立應用程式物件


資源檔的設定與使用

  • 在VC++中的File選New, 再點選Files中的Resource Template進行script的編輯.

  • 再點選Insert中的Resource進行資源檔的編輯.

  • 編輯完畢後, 再將script存成*.rc的檔案格式, 再到Resource Files中將剛才存檔的.rc import進來即可.


程式說明

我們將利用MyFrame程式範例介紹下列重點

  • 視窗框架與資源檔

  • 視窗元件的使用


程式說明

在上述程式中在MyFrame類別中, 亦有一個指向Cmenu物件的FMenu指標屬性,當您要操作該選單時(如: 新增, 刪除等等)可透過CMenu來完成.

而在第17行利用LoadMenu將定義在資源檔中的選單代號載入, 再利用SetMenu函數將Fmneu設定為視窗使用的選單


程式說明

在視窗框架類別中是負責產生應用程式物件所使用的視窗框架物件, 也就是應用程式的視窗介面, 所以資源檔中定義的資源大部份都是建立視窗框架時所用的元件

#include "MyFrame.h" //由資源編輯器所產生的標頭檔


程式說明

// 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


視窗的訊息傳遞與處理

在視窗作業系統下, 作業系統將不斷由電腦系統的週邊裝置得到訊息, 就連您輕輕的移動了一下滑鼠, 作業系統也會收到滑鼠移動的訊息.

在多而繁雜的訊息中, 如何讓應用程式知道究竟哪些訊息要回應? 要如何回應呢? 這要透過訊息映射表的建立.


視窗訊息的種類

回應訊息與處理函數分為兩種

  • 標準系統訊息

    標準系統訊息是由作業系統所產生的訊息, 比如: 移動滑鼠或按下滑鼠左鍵…等. 而接收並處理這類標準系統訊息的類別, 必須衍生自CWnd類別.

    定義的方式通常以ON_WM_XXX方式定義

    BEGIN_MESSAGE_MAP(類別名稱,基礎類別名稱)

    ON_WM_LBUTTONDOWN()

    ON_WM_MOUSEMOVE()

    ON_WM_LBUTTONUP()

    END_MESSAGE_MAP()


視窗訊息的種類

而回應系統訊息名稱, MFC均已定義, 其宣告方式如下

afx_msg void OnLButtonDown(UINT nFlags, CPoint point)

{……; }//當滑鼠左鍵按下後的回應函數,取得滑鼠訊息接收權

其中nFlags與point為傳入函數的參數.


視窗訊息的種類

  • 命令訊息

    命令訊息大致上是指由使用者自行定義的選單.工具列.

    控制項…等視窗元件, 被選取時所產生的訊息. 回應這類訊息的類別必須衍生自CCmdTarget類別. 這類訊息回息回應項目的定義方式如下:

    BEGIN_MESSAGE_MAP類別名稱,基礎類別名稱)

    ON_COMMAND(訊息代號,回應函數)

    END_MESSAGE_MAP()


視窗訊息的種類

命令訊息必須在建立該命令時, 即建立一個代號, 這個代號, 就是建立資源物件時設定的資源代號, 比如: 我們在定義File選單的Exit選項為ID_EXIT1. 而回應函數的名稱也必須由我們定義,比如: 我們在定義File選單的Exit函數名稱為ONExit. 而在宣告這類訊息處理函數時, 我們必須在該函數前加afx_msg, 定義方式如下:

afx_msg void 回應函數名稱(參數…)

ex:afx_msg void OnExit() //ID_EXIT1的回應函數

對於一些大部份視窗程式常用到的命令, MFC亦定義了代號(Standard Command Ids)


訊息映射表的建立

DECLARE_MESSAGE_MAP() //宣告訊息映射表

然後在類別外宣告所處理的訊息, 以及處理函數.

BEGIN_MESSAGE_MAP(MyFrame, CFrameWnd)

//建立MyFrame類別的訊息映射表

訊息回應項目

END_MESSAGE_MAP()


訊息映射表的建立

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()

函數名稱

訊息代號


Mouse
Mouse訊息傳入的參數

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


繪圖相關說明

  • SetCapture(); //當滑鼠左鍵按下後的回應函數,取得滑鼠訊息接收權

  • CClientDC aDC(this); //建立一個畫布

    aDC.SetPixel(point, RGB(255, 0 ,0));//利用SetPixel在畫布上點出紅點

  • GetCapture() //判斷滑鼠游標是否在視窗之上

  • ReleaseCapture() //當滑鼠左鍵放開後的回應函數,釋放滑鼠訊息接收權


Message

#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程式範例


Message1

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程式範例


Document view
Document/View的基本架構

Document/view(文件/瀏覽)的架構, 就是用來管理視窗介面下, 資料的儲存與顯示, 在分工上, Document物件用於管理視窗程式的資料儲存, 而View物件負責將Document儲存的資料正確顯示在視窗上.

一個完整的視窗應用程式, 必須具備有應用程式類別(CWinApp).視窗框架類別(CFrameWnd).Document類別(文件類別).View類別(瀏覽類別).


Document view1
Document/View的基本架構

視窗框架物件

應用程式物件

Document物件

View物件


重新整理

  • 應用程式物件用於建立應用程式

  • 視窗框架物件用於建立視窗介面

  • Document物件用於運作.儲存資料

  • View物件用於將Document物件顯示於視窗

  • 從資料的角度來看, Document物件與View物件其實是一體的, 只是將資料的處理與顯示的工作分開


Document view2

應用程式物件

Pointer

文件樣版物件物件

文件物件

Pointer

Pointer

瀏覽物件

Pointer

Document/View架構圖

1.產生

指向

視窗框架物件

3.產生

2.產生

Pointer

4.產生


Document view3

#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程式範例


Document view4

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程式範例


程式說明

宣告Run-Time類別

因為CSignleDocument在無法得知視窗框架物件.Vie w類別.Document類別的情況下,等到執行時才決定運用哪幾個類別的應用程式.

宣告

DECLARE_DYNAMIC(類別名稱)

然後在該類別外做如下宣告

IMPLEMENT_DYNAMIC(類別名稱,衍生類別名稱)


Document view5

#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架構的應用視窗的重繪


Document view6

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架構的應用視窗的重繪


Document view7

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架構的應用視窗的重繪


Document view8

class MyApp : public CWinApp ReleaseCapture(); }

{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架構的應用視窗的重繪


程式說明 ReleaseCapture(); }

  • 利用MFC所提供的容器類別 Carray類別, 將滑鼠在視窗中移動時, 傳入的軌跡點存起來.

  • Carray的宣告方式:

    Carray<儲存的資料型別,讀取儲存資料的傳回值>

    函數說明

  • void AddPoint(Cpoint p)//將軌跡點加入容器中.

  • Cpoint GetPoint(int i)//從容器中取得軌跡點.

  • Int GetSize()//取得軌跡點的大小.


ad