第三部分: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 <afxwin.h>
// 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 选项来查找。所有相关的函数都会列出来的。编译多个可执行程序
在本教程中,有几个例子程序。有两种方式来编译和运行它们。第一种方式是把每个程序都放到自己的目录中,然后为每个程序分别建立一个项目。使用该技术,你可以分别编译每个程序,并且可以同时或独立地使用他们。该方法的缺点是需要比较大的磁盘空间。
第二种方法是为所有的程序只建立一个目录。你可以一个项目文件。为了编译每个程序,你可以编辑项目和改变源文件。当你重新编译项目时,新的可执行程序就是你所选择的源文件的。该方法可以使用减少磁盘空间。