?? visual c++ mfc +=+
字號:
在上面的列表中,有幾點需要注意。第一,MFC 中的大部分類都是從基類 CObject 中繼承下來的。該類包含有大部分MFC類所通用的數(shù)據(jù)成員和成員函數(shù)。第二,是該列表的簡單性。CWinApp 類是在你建立應(yīng)用程序是要用到的,并且任何程序中都只用一次。CWnd 類匯集了 Windows 中的所有通用特性、對話框和控制。CFrameWnd 類是從 CWnd 繼承來的,并實現(xiàn)了標準的框架應(yīng)用程序。CDialog 可分別處理無模式和有模式兩種類型的對話框。CView 是用于讓用戶通過窗口來訪問文檔。最后,Windows 支持六種控制類型: 靜態(tài)文本框、可編輯文本框、按鈕、滾動條、列表框和組合框(一種擴展的列表框)。一旦你理解了這些,你也就能更好的理解 MFC 了。MFC 中的其它類實現(xiàn)了其它特性,如內(nèi)存管理、文檔控制等。
為了建立一個MFC應(yīng)用程序,你既要會直接使用這些類,而通常你需要從這些類中繼承新的類。在繼承的類中,你可以建立新的成員函數(shù),這能更適用你自己的需要。你在第一講中的簡單例子中已經(jīng)看到了這種繼承過程,下面會詳細介紹。CHelloApp 和 CHelloWindow 都是從已有的 MFC 類中繼承的。
設(shè)計一個程序
在討論代碼本身之前,我們需要花些工夫來簡單介紹以下 MFC 中程序設(shè)計的過程。例如,假如你要編一個程序來向用戶顯示“Hello World”信息。這當然是很簡單的,但仍需要一些考慮。
“hello world”應(yīng)用程序首先需要在屏幕上建立一個窗口來顯示“hello world”。然后需要實際把“hello world”放到窗口上。我們需要但個對象來完成這項任務(wù):
1. 一個應(yīng)用程序?qū)ο?,用來初始化?yīng)用程序并把它掛到 Windows 上。該應(yīng)用程序?qū)ο筇幚硭械牡图壥录?2. 一個窗口對象來作為主窗口。
3. 一個靜態(tài)文本對象,用來顯示“hello world”。
你用 MFC 所建立的每個程序都會包含頭兩個對象。第三個對象是針對該應(yīng)用程序的。每個應(yīng)用程序都會定義它自己的一組用戶界面對象,以顯示應(yīng)用程序的輸出和收集應(yīng)用的輸入信息。
一旦你完成了界面的設(shè)計,并決定實現(xiàn)該界面所需要的控制,你就需要編寫代碼來在屏幕上建立這些控制。你還會編寫代碼來處理用戶操作這些控制所產(chǎn)生的信息。在“hello world”應(yīng)用程序中,只有一個控制。它用來輸出“hello world”。復雜的程序可能在其主窗口和對話框中需要上百個控制。
應(yīng)該注意,在應(yīng)用程序中有兩種不同的方法來建立用戶控制。這里所介紹的是用 C++ 代碼方式來建立控制。但是,在比較大的應(yīng)用程序中,這種方法是不可行的。因此,在通常情況下要使用資源文件的圖形編輯器來建立控制。這種方法要方便得多。
理解“hello world”的代碼
下面列出了你在上一講中已經(jīng)輸入、編譯和運行的“hello world”程序的代碼。添加行號是為了討論方便。我們來一行行地研究它,你會更好的理解 MFC 建立應(yīng)用程序的方式。
如果你還沒有編譯和運行該代碼,應(yīng)該按上一講的方法去做。
1 //hello.cpp
2 #include <afxwin.h>
3 // Declare the application class
4 class CHelloApp : public CWinApp
5 {
6 public:
7 virtual BOOL InitInstance();
8 };
9 // Create an instance of the application class
10 CHelloApp HelloApp;
11 // Declare the main window class
12 class CHelloWindow : public CFrameWnd
13 {
14 CStatic* cs;
15 public:
16 CHelloWindow();
17 };
18 // The InitInstance function is called each
19 // time the application first executes.
20 BOOL CHelloApp::InitInstance()
21 {
22 m_pMainWnd = new CHelloWindow();
23 m_pMainWnd->ShowWindow(m_nCmdShow);
24 m_pMainWnd->UpdateWindow();
25 return TRUE;
26 }
27 // The constructor for the window class
28 CHelloWindow::CHelloWindow()
29 {
30 // Create the window itself
31 Create(NULL,
32 "Hello World!",
33 WS_OVERLAPPEDWINDOW,
34 CRect(0,0,200,200));
35 // Create a static label
36 cs = new CStatic();
37 cs->Create("hello world",
38 WS_CHILD|WS_VISIBLE|SS_CENTER,
39 CRect(50,80,150,150),
40 this);
41 }
你把上面的代碼看一遍,以得到一整體印象。該程序由六小部分組成,每一部分都起到很重要的作用。
首先,該程序包含了頭文件 afxwin.h (第 2 行)。該頭文件包含有 MFC 中所使用的所有的類型、類、函數(shù)和變量。它也包含了其它頭文件,如 Windows API 庫等。
第 3 至 8 行從 MFC 說明的標準應(yīng)用程序類 CWinApp 繼承出了新的應(yīng)用程序類 CHelloApp。該新類是為了要重載 CWinApp 中的 InitInstance 成員函數(shù)。InitInstance 是一個應(yīng)用程序開始執(zhí)行時要調(diào)用的可重載函數(shù)。
在第10行中,說明了應(yīng)用程序作為全局變量的一個事例。該實例是很重要的,因為它要影響到程序的執(zhí)行。當應(yīng)用程序被裝入內(nèi)存并開始執(zhí)行時,全局變量的建立會執(zhí)行 CWinApp 類的缺省構(gòu)造函數(shù)。該構(gòu)造函數(shù)會自動調(diào)用在18至26行定義的 InitInstance 函數(shù)。
在第11至17中,CHelloWindow 類是從 MFC 中的 CFrameWnd 類繼承來的。CHelloWindow 是作為應(yīng)用程序在屏幕上的窗口。建立新的類以便實現(xiàn)構(gòu)造函數(shù)、析構(gòu)函數(shù)和數(shù)據(jù)成員。
第18至26行實現(xiàn)了 InitInstance 函數(shù)。該函數(shù)產(chǎn)生一個 CHelloWindow 類的事例,因此會執(zhí)行第27行至41行中類的構(gòu)造函數(shù)。它也會把新窗口放到屏幕上。
第27至41實現(xiàn)了窗口的構(gòu)造函數(shù)。該構(gòu)造函數(shù)實際是建立了窗口,然后在其中建立一個靜態(tài)文本控制。
要注意的是,在該程序中沒有 main 或 WinMain 函數(shù),也沒有事件循環(huán)。然而我們從上一講在執(zhí)行中知道它也處理了事件。窗口可以最大或最小化、移動窗口等等。所有這些操作都隱藏在主應(yīng)用程序類 CWinApp 中,并且我們不必為它的事件處理而操心,它都是自動執(zhí)行、在 MFC 中不可見的。
下一節(jié)中,將詳細介紹程序的各部分。你可能不能馬上全都理解得很好: 但你最好先讀完它以獲得第一印象。在下一講中,會介紹一些特殊的例子,并偶把各片段組合在一起,有助于你能更好的理解。
程序?qū)ο?用 MFC 建立的每個應(yīng)用程序都要包括一個單一從 CWinApp 類繼承來的應(yīng)用程序?qū)ο?。該對象必須被說明成全局的(第10行),并且在你的程序中只能出現(xiàn)一次。
從 CWinApp 類繼承的對象主要是處理應(yīng)用程序的初始化,同時也處理應(yīng)用程序主事件循環(huán)。CWinApp 類有幾個數(shù)據(jù)成員和幾個成員函數(shù)。在上面的程序中,我們只重載了一個 CWinApp 中的虛擬函數(shù) InitInstance。
應(yīng)用程序?qū)ο蟮哪康氖浅跏蓟涂刂颇愕某绦?。因?Windows 允許同一個應(yīng)用程序的多個事例在同時執(zhí)行,因此 MFC 把初始化過程分成兩部分并使用兩個函數(shù) InitApplication 和 InitInstance 來處理它。此處,我們只使用了一個 InitInstance 函數(shù),因為我們的程序很簡單。當每次調(diào)用應(yīng)用程序時都會調(diào)用一個新的事例。第3至8行的代碼建立了一個稱為 CHelloApp 的類,它是從 CWinApp 繼承來的。它包含一個新的 InitInstance 函數(shù),是從 CWinApp 中已存在的函數(shù)(不做任何事情)重載來的:
3 // Declare the application class
4 class CHelloApp : public CWinApp
5 {
6 public:
7 virtual BOOL InitInstance();
8 };
在重載的 InitInstance 函數(shù)內(nèi)部,第18至26行,程序使用 CHelloApp 的數(shù)據(jù)成員 m_pMainWnd 來建立并顯示窗口:
18 // The InitInstance function is called each
19 // time the application first executes.
20 BOOL CHelloApp::InitInstance()
21 {
22 m_pMainWnd = new CHelloWindow();
23 m_pMainWnd->ShowWindow(m_nCmdShow);
24 m_pMainWnd->UpdateWindow();
25 return TRUE;
26 }
InitInstance 函數(shù)返回 TRUE 表示初始化已成功的完成。如果返回了FALSE,則表明應(yīng)用程序會立即終止。在下一節(jié)中我們將會看到窗口初始化的詳細過程。
當應(yīng)用程序?qū)ο笤诘?0行建立時,它的數(shù)據(jù)成員(從 CWinApp 繼承來的) 會自動初始化。例如,m_pszAppName、m_lpCmdLine 和 m_nCmdShow 都包含有適當?shù)某跏蓟怠D憧蓞⒁?MFC 的幫助文件來獲得更詳細的信息。我們將使用這些變量中的一個。
窗口對象
MFC 定義了兩個類型的窗口: 1) 框架窗口,它是一個全功能的窗口,可以改變大小、最小化、最大化等等; 2) 對話框窗口,它不能改變大小??蚣艽翱谑堑湫偷闹鲬?yīng)用程序窗口。
在下面的代碼中,從 CFrameWnd 中繼承了一個新的類 CHelloWindow:
11 // Declare the main window class
12 class CHelloWindow : public CFrameWnd
13 {
14 CStatic* cs;
15 public:
16 CHelloWindow();
17 };
它包括一個新的構(gòu)造函數(shù),同時還有一個指向程序中所使用的唯一用戶界面控制的數(shù)據(jù)成員。你多建立的每個應(yīng)用程序在主窗口中都會有唯一的一組控制。因此,繼承類將有一個重載的構(gòu)造函數(shù)以用來建立主窗口所需要的所有控制。典型情況下,該類會包含有一個析構(gòu)函數(shù)以便在窗口關(guān)閉時來刪除他們。我們這里沒有使用析構(gòu)函數(shù)。在第四講中,我們將會看到繼承窗口類也會說明一個消息處理函數(shù)來處理這些控制在響應(yīng)用戶事件所產(chǎn)生的消息。
典型地,一個應(yīng)用程序?qū)⒂幸粋€主應(yīng)用程序窗口。因此,CHelloApp 應(yīng)用程序類定義了一個名為 m_pMainWnd 成員變量來指向主窗口。為了建立該程序的主窗口,InitInstance 函數(shù)(第18至26行)建立了一個 CHelloWindow 事例,并使用 m_pMainWnd 來指向一個新的窗口。我們的 CHelloWindow 對象是在第22行建立的:
18 // The InitInstance function is called each
19 // time the application first executes.
20 BOOL CHelloApp::InitInstance()
21 {
22 m_pMainWnd = new CHelloWindow();
23 m_pMainWnd->ShowWindow(m_nCmdShow);
24 m_pMainWnd->UpdateWindow();
25 return TRUE;
26 }
只建立一個簡單的框架窗口是不夠的。還要確保窗口能正確地出現(xiàn)在屏幕上。首先,代碼必須要調(diào)用窗口的 ShowWindow 函數(shù)以使窗口出現(xiàn)在屏幕上(第23行)。其次,程序必須要調(diào)用 UpdateWindow 函數(shù)來確保窗口中的每個控制和輸出能正確地出現(xiàn)在屏幕上(第24行)。
你可能奇怪,ShowWindow 和 UpdateWindow 函數(shù)是在哪兒定義的。例如,如果你要查看以便了解它們,你可能要查看 MFC 的幫助文件中的 CFrameWnd 定義部分。但是 CFrameWnd 中并不包含有這些成員函數(shù)。CFrameWnd 是從 CWnd 類繼承來的。你可以查看 MFC 文檔中的 CWnd,你會發(fā)現(xiàn)它包含有200多個不同的成員函數(shù)。顯然,你不能在幾分鐘內(nèi)掌握這些函數(shù),但是你可以掌握其中的幾個,如 ShowWindow 和UpdateWindow。
現(xiàn)在讓我們花幾分鐘來看一下 MFC 幫助文件中的 CWnd::ShowWindow 函數(shù)。為此,你你可以單擊幫助文件中的 Search 按鈕,并輸入“ShowWindow”。找到后,你會注意到,ShowWindow 只有一個參數(shù),你可以設(shè)置不同的參數(shù)值。我們把它設(shè)置成我們程序中 CHelloApp 的數(shù)據(jù)成員變量 m_nCmdShow (第23行)。m_nCmdShow 變量是用來初始化應(yīng)用程序啟動的窗口顯示方式的。例如,用戶可能在程序管理器中啟動應(yīng)用程序,并可通過應(yīng)用程序?qū)傩詫υ捒騺砀嬷绦蚬芾砥鲬?yīng)用程序在啟動時要保持最小化狀態(tài)。m_nCmdShow 變量將被設(shè)置成 SW_SHOWMINIMIZED,并且應(yīng)用程序會以圖標的形式來啟動,也就是說,程序啟動后,是一個代表該程序的圖標。m_nCmdShow 變量是一種外界與應(yīng)用程序通訊的方式。如果你愿意,你可以用不同的 m_nCmdShow 值來試驗 ShowWindow 的效果。但要重新編譯程序才能看到效果。
第22行是初始化窗口。它為調(diào)用 new 函數(shù)分配內(nèi)存。在這一點上,程序在執(zhí)行時會調(diào)用CHelloWindow的構(gòu)造函數(shù)。該構(gòu)造函數(shù)在每次帶類的事例被分配時都要調(diào)用。在窗口構(gòu)造函數(shù)的內(nèi)部,窗口必須建立它自己。它是通過調(diào)用 CFrameWnd 的 Create 成員函數(shù)來實現(xiàn)的(第31行):
27 // The constructor for the window class
28 CHelloWindow::CHelloWindow()
29 {
30 // Create the window itself
31 Create(NULL,
32 "Hello World!",
33 WS_OVERLAPPEDWINDOW,
34 CRect(0,0,200,200));
建立函數(shù)共傳遞了四個參數(shù)。通過查看 MFC 文檔,你可以了解不同類型。NULL 參數(shù)表示使用缺省的類名。第二個參數(shù)為出現(xiàn)在窗口標題欄上的標題。第三個參數(shù)為窗口的類型屬性。該程序使用了正常的、可覆蓋類型的窗口。在下一講中將詳細介紹類型屬性。第四個參數(shù)指出窗口應(yīng)該放在屏幕上的位置和大小,左上角為(0,0), 初始化大小為 200×200個象素。如果使用了 rectDefault,則 Windows 會為你自動放置窗口及大小。
因為我們的程序太簡單了,所以它只在窗口中建立了一個靜態(tài)文本控制。見第35至40行。下面將詳細介紹。
靜態(tài)文本控制
程序在從 CFrameWnd 類中繼承 CHelloWindow 類時(第11至17行)時,說明了一個成員類型 CStatic及其構(gòu)造函數(shù)。
正如在前面所見到的,CHelloWindow 構(gòu)造函數(shù)主要做兩件事情。第一是通過調(diào)用Create函數(shù)(第31行)來建立應(yīng)用程序的窗口。然后分配和建立屬于窗口的控制。在我們的程序中,只使用了一個控制。在 MFC 中建一個對象總要經(jīng)過兩步。第一是為類的事例分配內(nèi)存,然后是調(diào)用構(gòu)造函數(shù)來初始化變量。下一步,調(diào)用 Create 函數(shù)來實際建立屏幕上的對象。代碼使用這兩步分配、構(gòu)造和建立了一個靜態(tài)文本對象(第36至40行):
27 // The constructor for the window class
28 CHelloWindow::CHelloWindow()
29 {
30 // Create the window itself
31 Create(NULL,
32 "Hello World!",
33 WS_OVERLAPPEDWINDOW,
34 CRect(0,0,200,200));
35 // Create a static label
36 cs = new CStatic();
37 cs->Create("hello world",
38 WS_CHILD|WS_VISIBLE|SS_CENTER,
39 CRect(50,80,150,150),
40 this);
41 }
CStatic 構(gòu)造函數(shù)是在為其分配內(nèi)存時調(diào)用的,然后就調(diào)用了 Create 函數(shù)來建立 CStatic 控制的窗口。Create 函數(shù)所使用的參數(shù)與窗口建立函數(shù)所使用的參數(shù)是類似的(第31行)。第一個參數(shù)指定了控制中所要顯示的文本內(nèi)容。第二個參數(shù)指定了類型屬性。類型屬性在下一講中將詳細介紹。在次我們使用的是子窗口類型(既在別的窗口中顯示的窗口),還有它是可見的,還有文本的顯示位置是居中的。第三個參數(shù)決定了控制的大小和位置。第四參數(shù)表示該子窗口的父窗口。已經(jīng)建立了一個靜態(tài)控制,它將出現(xiàn)在應(yīng)用程序窗口上,并顯示指定的文本。
結(jié)論
第一次瀏覽該代碼,也可能不是很熟悉和有些讓人煩惱。但是不要著急。從程序員的觀點來看,整個程序的主要工作就是建立了 CStatic 控制(36至40行)。在下一講中,我們詳細向你介紹36至40行代碼的含義,并可看到定制 CStatic 控制的幾個選項。
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -