第三部分:MFC樣式
控制是用來建立Windows應用程序用戶界面的用戶界面對象。你所見到的大部分Windows應用程序和對話框只不過是由一些控制所組成的、用來實現程序功能的東西。為了建立有效的應用程序,你必須完全理解在Windows應用程序中應該如何合理的使用控制。有六個基本的控制:CStatic、CButton、CEdit、CList、CComboBox和CScrollBar。另外,Windows 95又增加了15增強了的控制。你需要理解的是那個控制能做些什麼、你應該如何控制它的外表和行為以及如何讓控制能響應用戶事件。只要掌握了這些,再加上掌握了菜單和對話框,你就可以建立你所想象的任何Windows應用程序。你可以象本教程這樣用程序代碼來建立控制,也可以使用資源編輯器通過資源文件來建立。當然,對話框編輯器更方便些,它對於已經基本掌握了控制的情況下特別有用。
最簡單的控制是CStatic, 它是用來顯示靜態文本的。CStatic類沒有任何數據成員,它只有少量的成員函數:構造函數、Create函數(用於獲取和設置靜態控制上的圖標)等等。它不響應用戶事件。因為它的簡單性,所以最好把它作為學習Windows控制的開端。
在本講中,我們從CStatic著手,看一下如何修改和定制控制。在下一講中,我們將學習CButton和CScrollBar類,以理解事件處理的概念。一旦你理解和掌握了所有控制極其類,你就可以建立完整的應用程序了。
基 礎
MFC中的CStatic類是用來顯示靜態文本信息的。這些信息能夠可以作為純信息(例如,顯示在信息對話框中的錯誤消息), 或作為小的標簽等。在Windows應用程序的文件打開對話框中,你會發現有六個這樣的標簽。
CStatic控制還有幾種其它的顯示格式。你可以通過修改標簽的樣式來使它表現為矩形、邊框或圖標等。
CStatic控制總是作為子窗口的形式出現的。典型情況下,其父窗口是應用程序的主窗口或對話框。正如上一講所介紹的,你用兩行代碼就可以建立一個靜態控制:
CStatic *cs;
...
cs = new CStatic();
cs->Create("hello world",
WS_CHILD|WS_VISIBLE|SS_CENTER,
CRect(50,80, 150, 150),
this);
這兩行代碼是典型的MFC建立所有控制的代碼。調用new來為CStatic類的事例分配內存,然後調用類的構造函數。構造函數是用來完成類所需要的初始化功能的。Create函數建立控制並把它放到屏幕上。
Create函數有五個參數:
lpszText: 指定了要顯示的文本。
rect: 控制文本區域的位置、大小和形狀。
pParentWnd: 指明CStatic控制的父窗口。該控制會出現在其父窗口中,且其位置是相對於其父窗口的用戶區域而言的。
nID: 整數值,表示該控制的標識符。
dwStyle: 最重要的參數。它控制著控制的外觀和行為。
CStatic樣式
所有的控制都有各種顯示樣式。樣式是在用Create函數建立控制時傳遞給它的dwStyle參數所決定的。對CStatic有效的樣式簡介如下:
從CWnd繼承來的樣式:
WS_CHILD CStatic所必須的。
WS_VISIBLE 表示該控制對用戶應該是可見的。
WS_DISABLED 表示該控制拒絕接受用戶事件。
WS_BORDER 控制的文本區域帶有邊框。
CStatic固有的樣式:
SS_BLACKFRAME 該控制區域以矩形邊界顯示。顏色與窗口框架相同。
SS_BLACKRECT ? 該控制以填充的矩形顯示。顏色與當前的窗口框架相同。
SS_CENTER 文本居中。
SS_GRAYFRAME 控制以矩形邊框方式顯示。顏色與當前桌面相同。
SS_GRAYRECT 該控制以填充的矩形顯示。顏色與當前的桌面相同。
SS_ICON 控制以圖標形式顯示。文本作為圖標在資源文件的名稱。rect參數只控制位置。
SS_LEFT 文本居左顯示。文字可回繞。
SS_LEFTNOWORDWRAP 文本居左顯示。多余的文字被剪裁。
SS_NOPREFIX 表示字符串中的"&"字符不表示為加速前綴。
SS_RIGHT 文本居右顯示。文字可回繞。
SS_SIMPLE 只簡單的顯示一行文本。任何CTLCOLOR信息都被其父窗口忽略。
SS_USERITEM 用戶定義項。
SS_WHITEFRAME 控制以矩形邊框方式顯示。顏色與當前窗口背景顏色相同。
SS_WHITERECT 控制以填充矩形方式顯示。顏色與當前窗口背景顏色相同。
這些常數中,“SS”(Static Style)開頭的表示只能用於CStatic控制。以“WS”(Window Style)開頭的常數表示可適用於所有窗口,它們定義在CWnd對象中。CWnd中還有很多以“WS”樣式常數。你可以在MFC文檔中的CWnd::Create函數中找到它們。上面的四種是只用於CStatic對象的。
CStatic對象至少要帶有兩個樣式:WS_CHILD和WS_VISIBLE。該控制必須作為另一窗口的子窗口來建立。如果不使用WS_VISIBLE,則所建立的控制是看不見的。WS_DISABLED控制著標簽對事件的響應,因為CStatic不接收鍵盤或鼠標事件,所以使用該項是多余的。
所有的其它樣式選項都是可選的,它們控制著標簽的外觀。在CStatic::Create函數中使用這些控制,可以控制CStatic在屏幕上的顯示。
CStatic文本的外觀
下面的代碼對於理解CStatic是有幫助的。它與上一講中介紹的代碼類似,但是修改了CStatic的建立部分。
//static1.cpp
#include
// Declare the application class
class CTestApp : public CWinApp
{
public:
virtual BOOL InitInstance();
};
// Create an instance of the application class
CTestApp TestApp;
// Declare the main window class
class CTestWindow : public CFrameWnd
{
CStatic* cs;
public:
CTestWindow();
};
// The InitInstance function is called
// once when the application first executes
BOOL CTestApp::InitInstance()
{
m_pMainWnd = new CTestWindow();
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
return TRUE;
}
// The constructor for the window class
CTestWindow::CTestWindow()
{
CRect r;
// Create the window itself
Create(NULL,
"CStatic Tests",
WS_OVERLAPPEDWINDOW,
CRect(0,0,200,200));
// Get the size of the client rectangle
GetClientRect(&r);
r.InflateRect(-20,-20);
// Create a static label
cs = new CStatic();
cs->Create("hello world",
WS_CHILD|WS_VISIBLE|WS_BORDER|SS_CENTER,
r,
this);
}
下面是窗口構造函數加上了行編號:
CTestWindow::CTestWindow()
{
CRect r;
// Create the window itself
1 Create(NULL,
"CStatic Tests",
WS_OVERLAPPEDWINDOW,
CRect(0,0,200,200));
// Get the size of the client rectangle
2 GetClientRect(&r);
3 r.InflateRect(-20,-20);
// Create a static label
4 cs = new CStatic();
5 cs->Create("hello world",
WS_CHILD|WS_VISIBLE|WS_BORDER|SS_CENTER,
r,
this);
}
首先在單擊1行中調用CTestWindow::Create函數。它是CFrameWnd對象的Create函數,因為CTestWindow從CFrameWnd繼承了其行為。所以第一行中的代碼指定了窗口大小應該為200×200個象素,窗口的左上角被初始化在屏幕的0,0位置處。常數rectDefault可用CRect參數來替代。
在第2行,調用了CTestWindow::GetClientRect,向它傳遞了&r參數。GetClientRect函數是從CWnd類繼承來的。變量r是CRect類型的,並且在函數的開頭部分被說明為局部變量。
理解這段代碼時可能會有兩個問題 1) GetClientRect函數是干什麼的? 2) CRect變量是干什麼的? 讓我們先回答第一個問題。當你查看MFC文檔中的CWnd::GetClientRect函數時,你會發現它返回一CRect類型,它包含了指定窗口的用戶區域矩形。它保存的是參數的地址&r。該地址指向CRect的位置。CRect類型是在MFC中定義的。用它處理矩形是非常方便的。如果你看以下MFC文檔,就會看到其中定義了30多種處理矩形的成員函數和操作符。
在我們的情況下,我們要在窗口中間顯示“Hello World”。因此,我們用GetClientRect來獲取用戶區域的矩形坐標。在第3行中調用了CRect::InflateRect,同時還可以增大或減少了矩形的尺寸(參見CRect::DeflateRect)。這裡我們對矩形的各邊減少了20個象素。如果不這樣的話,標簽周圍邊界就會超出窗口框架。
實際上,CStatic是在第4和5行建立的。樣式屬性為居中並有邊框。其大小和位置由CRect參數r確定的。
通過修改不同的樣式屬性,你可以理解CStatic的不同形式。例如,下面的代碼包含有對CTestWindow構造函數進行了修改,所產生的控制有個位移:
CTestWindow::CTestWindow()
{
CRect r;
// Create the window itself
Create(NULL,
"CStatic Tests",
WS_OVERLAPPEDWINDOW,
CRect(0,0,200,200));
// Get the size of the client rectangle
GetClientRect(&r);
r.InflateRect(-20,-20);
// Create a static label
cs = new CStatic();
cs->Create("Now is the time for all good men to \
come to the aid of their country",
WS_CHILD|WS_VISIBLE|WS_BORDER|SS_CENTER,
r,
this);
}
上面的代碼除了所顯示的文本比較長外沒有什麼不同。運行該代碼你就可以看到,CStatic在指定的區域內的文本已經回繞了,且沒一行都是居中的。
如果邊框矩形太小不能包含所有的文本行,則文本會被剪切以適應之。你減小矩形大小或增大字符串長度就可以看到CStatic的該特性。
在我們所看到的所有代碼中,樣式SS_CENTER是用來居中文本的。CStatic也允許左對齊或右對齊。左對齊是用SS_LEFT來替代SS_CENTER屬性。同樣,右對齊是用SS_RIGHT來取代之。
SS_LEFTNOWORDWRAP屬性是用來關閉文本回繞的。它會強迫使用左對齊屬性。
CStatic的矩形顯示模式
CStatic也支持兩種不同的矩形顯示模式:填充矩形和框架。通常用這兩種模式來把一組控制框在一起。例如,你可以把黑背景框架窗口作為一組編輯框的背景。你可以選擇六種不同的樣式: SS_BLACKFRAME、SS_BLACKRECT、SS_GRAYFRAME、SS_GRAYRECT、SS_WHITEFRAME和SS_WHITERECT。RECT形成了一個填充的矩形,而FRAME組成一邊框。其中的顏色標志,如SS_WHITERECT表示其顏色與窗口背景的顏色是相同的。盡管該顏色的缺省值是白色,但你可以使用控制面板來改變,此時矩形的顏色可能就不是白色的了。
當指定了矩形或框架屬性後,CStatic的文本字符串會被忽略。典型情況是傳遞一空字符串。你可以試驗以下這些特性。
字體
你可以使用CFont類來改變CStatic的字體。MFC中的CFont類保存著特殊Windows字體的單一實例。例如,一個實例的CFont類可能保存有18點的Times字體,而另一個可能保存著10點的Courier字體。你可以調用SetFont函數來修改字體。下面的代碼給出了如何實現字體。
CTestWindow::CTestWindow()
{
CRect r;
// Create the window itself
Create(NULL,
"CStatic Tests",
WS_OVERLAPPEDWINDOW,
CRect(0,0,200,200));
// Get the size of the client rectangle
GetClientRect(&r);
r.InflateRect(-20,-20);
// Create a static label
cs = new CStatic();
cs->Create("Hello World",
WS_CHILD|WS_VISIBLE|WS_BORDER|SS_CENTER,
r,
this);
// Create a new 36 point Arial font
font = new CFont;
font->CreateFont(36,0,0,0,700,0,0,0,
ANSI_CHARSET,OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,
DEFAULT_PITCH|FF_DONTCARE,
"arial");
// Cause the label to use the new font
cs->SetFont(font);
}
上面的代碼開始於建立窗口和CStatic。然後建立一CFont類型對象。字體變量應作為CTestWindow的數據成員來說明“CFont *font”。CFont::CreateFont函數有15個參數,但是只有三個是最常用的。例如,36指定了以點為單位的字體大小,700指定了字體的密度(400是正常“normal”, 700為加黑“bold”,值的范圍為1到1000。FW_NORMAL和FW_BOLD的含義實際上是相同的),“arial”是所用字體的名稱。Windows 通常帶有五種True Type字體(Arial、Courier New、Symbol、Times New Roman和Wingdings),使用它們,你可以確保任何機器上都會有該字體。如果你使用了系統不知道的字體,則CFont會選擇缺省字體,正如你在本教程所見到的。
要想更多的了解CFont類,可參見MFC文檔。在API在線幫助文件中,有一篇文章對字體做了很好的概述。查找“Fonts and Text Overview”。
SetFont函數是從CWnd繼承來的。它是用來設置窗口的字體的,在我們的程序中是CStatic子窗口。你可能要問:“我怎樣知道CWnd中的哪些函數可以用於CStatic在?”你只能在實踐中來學習。花上一些時間來看一下CWnd的所有函數。你定會有所收獲,並會發現哪些函數可用於定制控制。我們在選下一講中看到CWnd類中的其它Set函數。
結論
在本教程中,我們勘察了CStatic的很多不同特性。有關從CWnd繼承來的Set函數,我們將放到下一講介紹,因為在那裡更合適。
查看Microsoft文檔中的函數
在Visual C++ 5.x中,查找你多不熟悉的函數是很簡單的。所有的MFC、SDK、Windows API和C/C++標准庫函數都繼承到同一個幫助系統中了。如果你不能確定所要的函數在哪兒,你可以使用幫助菜單中的Search選項來查找。所有相關的函數都會列出來的。
編譯多個可執行程序
在本教程中,有幾個例子程序。有兩種方式來編譯和運行它們。第一種方式是把每個程序都放到自己的目錄中,然後為每個程序分別建立一個項目。使用該技術,你可以分別編譯每個程序,並且可以同時或獨立地使用他們。該方法的缺點是需要比較大的磁盤空間。
第二種方法是為所有的程序只建立一個目錄。你可以一個項目文件。為了編譯每個程序,你可以編輯項目和改變源文件。當你重新編譯項目時,新的可執行程序就是你所選擇的源文件的。該方法可以使用減少磁盤空間。