• 沒有找到結果。

如何撰寫視窗程式 如何撰寫視窗程式

N/A
N/A
Protected

Academic year: 2022

Share "如何撰寫視窗程式 如何撰寫視窗程式"

Copied!
40
0
0

加載中.... (立即查看全文)

全文

(1)

使用 使用 MFC 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 MFC 的 的 Example 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)

程式說明 程式說明

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

1. 繼承CWinApp類別

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

class MyApp : public CWinApp //繼承CWinApp {

public:

BOOL InitInstance() //程式進入點 {…}

};

(8)

程式說明 程式說明

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

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

1. 產生視窗框架物件

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

3. 在螢幕中建立視窗框架

4. 顯示視窗框架物件

(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

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); //設定視窗所使用的選單 }

};

(12)

MyFrame

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)

資源檔的設定與使用 資源檔的設定與使用

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

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

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

(14)

程式說明 程式說明

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

1. 視窗框架與資源檔

2. 視窗元件的使用

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

視窗訊息的種類 視窗訊息的種類

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

1. 標準系統訊息

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

視窗訊息的種類 視窗訊息的種類

2. 命令訊息

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

控制項…等視窗元件, 被選取時所產生的訊息. 回應這 類訊息的類別必須衍生自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 訊息傳入的參數 訊息傳入的參數

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

旗標 說明

MK_CONTROL 鍵盤上的CTRL被按下

MK_MBUTTON Mouse的中間按鍵被按下

MK_RBUTTON Mouse的右邊按鍵被按下

MK_SHIFT 鍵盤上的shift被按下

(26)

繪圖相關說明 繪圖相關說明

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

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

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

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

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

(27)

Message

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(); } //當滑鼠 左鍵放開後的回應函數,釋放滑 鼠訊息接收權

(28)

Message

Message 程式範例 程式範例

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

(29)

Document/View

Document/View 的基本架構 的基本架構

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

一個完整的視窗應用程式, 必須具備有應用程 式類別(CWinApp).視窗框架類別

(CFrameWnd).Document類別(文件類別).View類

別(瀏覽類別).

(30)

Document/View

Document/View 的基本架構 的基本架構

Document物件 View物件

視窗框架物件 應用程式物件

(31)

重新整理 重新整理

1. 應用程式物件用於建立應用程式

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

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

4. View物件用於將Document物件顯示於視窗

5. 從資料的角度來看, Document物件與View物件

其實是一體的, 只是將資料的處理與顯示的工

作分開

(32)

Document/View

Document/View 架構圖 架構圖

應用程式物件

Pointer

指向

文件樣版物件物件 Pointer

文件物件 Pointer 視窗框架物件

Pointer 1.產生

3.產生 2.產生 瀏覽物件

Pointer 4.產生

(33)

Document/View

Document/View 程式範例 程式範例

#include <afxwin.h>

#include "Doc_View.h"

class MyDocument : public CDocument

{DECLARE_DYNCREATE(MyDocu ment) //宣告run-time類別};

IMPLEMENT_DYNCREATE(MyDoc ument, CDocument)

//宣告MyDocument為run-time類別 class MyView : public CView

{public:

void OnDraw(CDC * aDC)

//必須過載的虛擬函數 { }

DECLARE_DYNCREATE(MyView)/

/宣告run-time類別};

IMPLEMENT_DYNCREATE(MyVie w, CView)

//宣告MyView為run-time類 別

class MyFrame : public CFrameWnd {

DECLARE_DYNCREATE(MyFra me) //宣告run-time類別

};

IMPLEMENT_DYNCREATE(MyFra me, CFrameWnd)

//宣告MyFrame為run-time 類別

(34)

Document/View

Document/View 程式範例 程式範例

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(MyVie w)); //單文件視窗的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;//建立應用程 式物件

(35)

程式說明 程式說明

宣告Run-Time類別

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

宣告

DECLARE_DYNAMIC(類別名稱) 然後在該類別外做如下宣告

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

(36)

Document/View

Document/View 架構的應用 架構的應用 視窗的重繪

視窗的重繪

#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(MyDo cument) //宣告為run-time 類別

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

};

IMPLEMENT_DYNCREATE(MyDoc ument, CDocument)

//建立run-time類別

BEGIN_MESSAGE_MAP(MyDocum ent, CDocument)

END_MESSAGE_MAP() //建立訊息映射表

(37)

Document/View

Document/View 架構的應用 架構的應用 視窗的重繪

視窗的重繪

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物件中

}}

(38)

Document/View

Document/View 架構的應用 架構的應用 視窗的重繪

視窗的重繪

afx_msg void OnLButtonUp(UINT, CPoint point){ ReleaseCapture(); } //釋放滑鼠訊息的接收權

DECLARE_DYNCREATE(MyVie w) //宣告為run-time類別

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

IMPLEMENT_DYNCREATE(MyVie w, 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(MyFra me) //宣告為run-time類別

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

};

IMPLEMENT_DYNCREATE(MyFra me, CFrameWnd)

//建立run-time類別

BEGIN_MESSAGE_MAP(MyFrame, CFrameWnd)

END_MESSAGE_MAP() //建立訊息映射表

(39)

Document/View

Document/View 架構的應用 架構的應用 視窗的重繪

視窗的重繪

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;

(40)

程式說明 程式說明

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

‹ Carray的宣告方式:

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

函數說明

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

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

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

參考文獻

相關文件

• 點選 Method Editor 來進行方法程式編輯(同樣,也可 在開啟後的視窗中,點選 Form Editor 來切回原視窗). Form

Simulink Block Library Browser),以及 (線上 支援視窗,Help

在撰寫網頁應用程式 HTML 的語法當中,以下何者錯誤?(A)&lt;a&gt;是用來製作超連結的標記(Tag) (B)HREF 是一個在&lt;a&gt;與&lt;/a&gt;中指定其他

檢視 檢視「 「 「 「輸出 輸出 輸出 輸出」 」 」 」視窗表示 視窗表示 視窗表示 視窗表示 程式碼沒有任何錯誤

在編輯/偵錯視窗 (Editor) 中,善用 “反白 MATLAB 宣告式. → 按下滑鼠右鍵 → 選取

• 透過觀察和實驗 透過觀察和實驗 透過觀察和實驗, 透過觀察和實驗 , , ,強化 強化 強化 強化、 、 、 、修訂 修訂 修訂

… 點選 LinkButton 控制 項的 (DataBindings) 屬性,在自訂繫結

卡繆《異鄉人》 張一喬譯 卡夫卡《變形記》 姬健梅譯 瑞蒙卡佛《大教堂》 余國芳譯. 吉本芭娜娜《白河夜船》