深入浅出MFC第2版(PDF格式)-第123部分
按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
异的绕行路线及其原因。
我在本章中挖出了许多MFC 源代码,希望藉由源代码的自我说明能力,加深你对消息
映射与消息绕行路径的了解。这是对MFC 「知其所以然」的重要关键。这个知识基础不
会因为MFC 的源代码更动而更动,我要强调的,是其原理。
599
…………………………………………………………Page 662……………………………………………………………
第篇 深入 MFC 程式設計
600
…………………………………………………………Page 663……………………………………………………………
10 MFC
第 章 與對話盒
10
第 章
MFC 与对话框
上一章我们为Scribble 新增了一个【Pen 】菜单,其中第二个命令项【Pen Width。。。 】准
备用来提供一个对话框,让使用者设定笔的宽度。每一线条都可以拥有自己的笔宽。原
预设粗笔是5个图素宽,细笔是2个图素宽。
为了这样的目的,在对话框中放个Spin 控制组件是极佳的选择。Spin 就是那种有着上下
小三角形箭头、可搭配一个文字显示器的控制组件,有点像转轮,用来选择数字最合适:
601
…………………………………………………………Page 664……………………………………………………………
第篇 深入 MFC 程式設計
但是,Scribble Step3 只是想示范如何在MFC 程序中经由菜单命令项唤起一个对话框,
并示范所谓的资料交换与资料检验(DDX/DDV)。所以,笔宽对话框中只选用两个小小
的Edit 控制组件而已。
本章还可以学习到如何利用对话框编辑器设计对话框的模板,并利用ClassWizard 制作
一个对话框类别,定义消息处理函数,把它们与对话框「绑」在一块儿。
图10…1 【Pen Widths】对话框
对话框编辑器
把对话框函数在一旁,把所有程序烦恼在一旁,我们先享受一下Visual C++ 整合环
境中的对话框编辑器带来的对话框模板(Dialog Template)设计快感。
设计对话框模板,有两个重要的步骤,第一是从工具箱中选择控制组件(control,功能
各异的小小零组件)加到对话框中,第二是填写此一控制组件的标题、ID 、以及其它性
质。
以下就是利用对话框编辑器设计【Pen Widths 】对话框的过程。
在Visual C++ 整合环境中选按【Insert/Resource 】命令项,并在随后而来的【Insert
Resource 】对话框中,选择【resource types 】为Dialog。
或是直接在Visual C++ 整合环境中按下工具栏的【New Dialog】按钮。
602
…………………………………………………………Page 665……………………………………………………………
10 MFC
第 章 與對話盒
Scribble。rc 文件会被打开,对话框编辑器出现,自动给我们一个空白对话框,内
含两个按钮,分别是【OK 】和【Cancel】。控制组件工具箱出现在画面右侧,
内含许多控制组件。
为了设定控制组件的属性,必须用到【Dialog Properties 】对话框。如果它最初
没有出现,只要以右键选按对话框的任何地方,就会跑出一份菜单,再选择其
中的! § Properties! ¨,即会出现此对话框。按下对话框左上方的push…pin 钮(大
头针) 可以常保它浮现为最上层窗口。现在把对话框ID 改为
IDD_PEN_WIDTHS ,把标题改为〃Pen Widths〃。
603
…………………………………………………………Page 666……………………………………………………………
第篇 深入 MFC 程式設計
为对话框加入两个Edit 控制组件,两个Static 控制组件,以及一个按钮。
右键选按新增的按钮,在Property page 中把其标题改为〃Default〃,并把ID
改为IDC_DEFAULT_PEN_ WIDTHS。
右键选按第一个Edit 控制组件, 在Property page 中把ID 改为
IDC_THIN_PEN_ WIDTH。以同样的方式把第二个Edit 控制组件的ID 改为
IDC THICK PEN WIDTH 。
_ _ _
604
…………………………………………………………Page 667……………………………………………………………
10 MFC
第 章 與對話盒
■右键选按第一个Static 控制组件,Property page 中出现其属性,现在把文字
内容改为〃Thin Pen Width: 〃。以同样的方式把第二个Static 控制组件的文字
内容改为〃Thick Pen Width: 〃。不必在意Static 控制组件的ID 值,因为我们
根本不可能在程序中用到Static 控制组件的ID 。
■调整每一个控制组件的大小位置,使之美观整齐。
■调整tab order 。所谓tab order 是使用者在操作对话框时,按下Tab 键后,键
盘输入焦点在各个控制组件上的巡回次序。调整方式是选按Visual C++ 整合环
境中的【Layout/Tab Order 】命令项,出现带有标号的对话框如下,再依你所想
要的次序以鼠标点选一遍即可。
■测试对话框。选按Visual C++ 整合环境中的【Layout/Test 】命令项,出现运作
状态下的对话框。你可以在这种状态下测试tab order 和预设按钮( default
button )。若欲退出,请选按【OK 】或【Cancel】或按下ESC 键。
注意:所谓default button ,是指与 键相通的那个按钮。
605
…………………………………………………………Page 668……………………………………………………………
第篇 深入 MFC 程式設計
所有调整都完成之后,存盘。于是SCRIBBLE。RC 增加了下列内容(一个对话框模板):
IDD_PEN_WIDTHS DIALOG DISCARDABLE 0; 0; 203; 65
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION 〃Pen Widths〃
FONT 8; 〃MS Sans Serif〃
BEGIN
DEFPUSHBUTTON 〃OK〃;IDOK;148;7;50;14
PUSHBUTTON 〃Cancel〃;IDCANCEL;148;24;50;14
PUSHBUTTON 〃Default〃;IDC_DEFAULT_PEN_WIDTHS;148;41;50;14
LTEXT 〃Thin Pen Width:〃;IDC_STATIC;10;12;70;10
LTEXT 〃Thick Pen Width:〃;IDC_STATIC;10;33;70;10
EDITTEXT IDC_THIN_PEN_WIDTH;86;12;40;13;ES_AUTOHSCROLL
EDITTEXT IDC_THICK_PEN_WIDTH;86;33;40;13;ES_AUTOHSCROLL
END
利用ClassWizard 连接对话框与其专属类别
一旦完成了对话框的外貌设计,再来就是设计其行为。我们有两件事要做:
1。 从MFC 的CDialog 中衍生出一个类别,用来负责对话框行为。
2。 利用ClassWizard 把这个类别和先前你产生的对话框资源连接起来。通常这意
味着你必须声明某些函数,用以处理你感兴趣的对话框消息,并将对话框中的
控制组件对应到类别的成员变量上,这也就是所谓的Dialog Data eXchange
(DDX )。如果你对这些变量内容有任何「确认规则」的话,ClassWizard 也
允许你设定之,这就是所谓的Dialog Data Validation (DDV) 。
注意:所谓「确认规则」是指对某些特殊用途的变量进行内容查验工作。例如月份
一定只可能在1~12 之间,日期一定只可能在1~31 之间,人名一定不会有数字夹
杂其中,金钱数额不能夹带文字,新竹的电话号码必须是03 开头后面再加7位数。。。
等等等。
606
…………………………………………………………Page 669……………………………………………………………
10 MFC
第 章 與對話盒
所有动作当然都可以手工完成,然而ClassWizard 的表现非常好,让我们快速又轻松地
完成这些事样。它可以为你的对话框产生一个。H 档,一个。CPP 文件,内有你的对话框
类别、函数骨干、一个Message Map 、以及一个Data Map 。哎呀,我们又看到了新东西,
稍后我会解释所谓的Data Map 。
回忆Scribble 诞生之初,程序中有一个About 对话框,寄生于SCRIBBLE。CPP 中。
AppWizard 并没有询问我们有关这个对话框的任何意见,就自作主张地放了这些码:
#0001 /////////////////////////////////////////////////////////////////
#0002 // CAboutDlg dialog used for App About
#0003
#0004 class CAboutDlg : public CDialog
#0005 {
#0006 public:
#0007 CAboutDlg();
#0008
#0009 // Dialog Data
#0010 //{{AFX_DATA(CAboutDlg)
#0011 enum { IDD = IDD_ABOUTBOX };
#0012 //}}AFX_DATA
#0013
#0014 // ClassWizard generated virtual function overrides
#0015 //{{AFX_VIRTUAL(CAboutDlg)
#0016 protected:
#0017 virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
#0018 //}}AFX_VIRTUAL
#0019
#0020 // Implementation
#0021 protected:
#0022 //{{AFX_MSG(CAboutDlg)
#0023 // No message handlers
#0024 //}}AFX_MSG
#0025 DECLARE_MESSAGE_MAP()
#0026 };
#0027
#0028 CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
#0029 {
#0030 //{{AFX_DATA_INIT(CAboutDlg)
#0031 //}}AFX_DATA_INIT
#0032 }
#0033
#0034 void CAboutDlg::DoDataExchange(CDataExchange* pDX)
607
…………………………………………………………Page 670……………………………………………………………
第篇 深入 MFC 程式設計
#0035 {
#0036 CDialog::DoDataExchange(pDX);
#0037 //{{AFX_DATA_MAP(CAboutDlg)
#0038 //}}AFX_DATA_MAP
#0039 }
#0040
#0041 BEGIN_MESSAGE_MAP(CAboutDlg; CDialog)
#0042 //{{AFX_MSG_MAP(CAboutDlg)
#0043 // No message handlers
#0044 //}}AFX_MSG_MAP
#0045 END_MESSAGE_MAP()
#0046
#0047 // App m