深入浅出MFC第2版(PDF格式)-第125部分
按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
■现在,【Member Functions 】清单中出现了新函数,以及它所对映之控制组件
与Notification 消息。
613
…………………………………………………………Page 676……………………………………………………………
第篇 深入 MFC 程式設計
按下【Edit Code 】钮,光标落在OnDefaultPenWidths 函数身上,我们看到以
下内容:
614
…………………………………………………………Page 677……………………………………………………………
10 MFC
第 章 與對話盒
上述动作对源代码造成的影响是:
// in PENDLG。H
class CPenWidthsDlg : public CDialog
{
protected:
afx_msg void OnDefaultPenWidths();
。。。
};
// in PENDLG。CPP
BEGIN_MESSAGE_MAP(CPenWidthsDlg; CDialog)
ON_BN_CLICKED(IDC_DEFAULT_PEN_WIDTHS; OnDefaultPenWidths)
END_MESSAGE_MAP()
void CPenWidthsDlg::OnDefaultPenWidths()
{
// TODO : Add your control notification handler here
}
MFC 中各式各样的MAP
如果你以为MFC 中只有Message Map 和Data Map ,那你就错了。另外还有一个
Dispatch Map ,使用于OLE Automation,下面是其形式:
DECLARE_DISPATCH_MAP() // 。H文件中的宏,声明 Dispatch Map 。
BEGIN_DISPATCH_MAP(CClikDoc; CDocument) // 。CPP 档中的 Dispatch Map
//{{AFX_DISPATCH_MAP(CClikDoc)
DISP_PROPERTY(CClikDoc; 〃text〃; m_str; VT_BSTR)
DISP_PROPERTY_EX(CClikDoc; 〃x〃; GetX; SetX; VT_I2)
DISP_PROPERTY_EX(CClikDoc; 〃y〃; GetY; SetY; VT_I2)
//}}AFX_DISPATCH_MAP
END_DISPATCH_MAP()
此外还有Event Map ,使用于OLE Custom Control (也就是OCX ),下面是其形式:
615
…………………………………………………………Page 678……………………………………………………………
第篇 深入 MFC 程式設計
档中的宏,声明 Event Map。
DECLARE_EVENT_MAP() // 。H
BEGIN_EVENT_MAP(CSmileCtrl; COleControl) // 。CPP 档中的 Event Map
//{{AFX_EVENT_MAP(CSmileCtrl)
EVENT_CUSTOM(〃Inside〃; FireInside; VTS_I2 VTS_I2)
EVENT_STOCK_CLICK()
//}}AFX_EVENT_MAP
END_EVENT_MAP()
至于Message Map ,我想你一定已经很熟悉了:
DECLARE_MESSAGE_MAP()// 。H文件中的宏,声明 Message Map
BEGIN_MESSAGE_MAP(CScribDoc; CDocument) // 。CPP 档中的Message Map
//{{AFX_MSG_MAP(CScribDoc)
ON_MAND(ID_EDIT_CLEAR_ALL; OnEditClearAll)
ON_MAND(ID_PEN_THICK_OR_THIN; OnPenThickOrThin)
ON_MAND(ID_PEN_WIDTHS; OnPenWidths)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
MFC 所谓的Map ,其实就是一种类似表格的东西,它的背后是什么?可能是一个巨大
的数据结构(例如Message Map )。最和其它Map 形式不同的,就属Data Map 了,
它的形式是:
//{{AFX_DATA_MAP(CPenWidthsDlg) // 。CPP
DDX_Text(pDX; IDC_THIN_PEN_WIDTH; m_nThinWidth);
DDV_MinMaxInt(pDX; m_nThinWidth; 1; 20);
DDX_Text(pDX; IDC_THICK_PEN_WIDTH; m_nThickWidth);
DDV_MinMaxInt(pDX; m_nThickWidth; 1; 20);
//}}AFX_DATA_MAP
针对同一个资料目标(成员变量),Data Map 之中每组有两笔记录,一笔负责DDX
一笔负责DDV。
,
616
…………………………………………………………Page 679……………………………………………………………
10 MFC
第 章 與對話盒
对话框数据交换与查核(DDX & DDV)
在解释DDX/DDV 的来龙去脉之前,我想先描述一下SDK 程序处理对话框资料的作法。
如果你设计一个对话框如下图:
当【OK 】钮被按下,程序应该一一取得按钮状态以及Edit 内容:
char _OpenName'128';
GetDlgItemText(hwndDlg; IDC_EDIT; _OpenName; 128);
If (IsDlgButtonChecked(hDlg;IDC_1))
。。。;
If (IsDlgButtonChecked(hDlg;IDC_2))
。。。;
If (IsDlgButtonChecked(hDlg;IDC_3))
。。。;
If (IsDlgButtonChecked(hDlg;IDC_4))
。。。;
// hDlg 代表对话框的窗口handle
虽然Windows 95 和Windows NT 有所谓的通用型对话框(mon Dialog,第6章末
尾曾介绍过),某些个标准对话框的设计因而非常简单,但非标准的对话框还是得像上
面那样自己动手。
MFC 的方式就简单多了。它提供的DDX (X 表示eXchange ),允许程序员事先设定控
制组件与变量的对应关系。我们不但可以令控制组件的内容一有改变就自动传送到变量
去,也可以藉MFC 提供的DDV (V 表示Validation )设定字段的合理范围。如果使用
617
…………………………………………………………Page 680……………………………………………………………
第篇 深入 MFC 程式設計
者在字段上键入超出合理范围的数字,就会在按下【OK 】后出现类似以下的画面:
资料的查核(Data Validation )其实是一件琐碎又耗人力的事情,各式各样的资料都应该
要检查其合理范围,程序才算面面俱到。例如日期字段绝不能允许12 以上的月份以及
31 以上的日子(如果程序还能自动检查2月份只有28 天而遇闰年有29 天那就更棒了);
金额字段里绝不能允许文字出现,电话号码字段一定只有9位(至少台湾目前是如此)。
为了解决这些琐碎又累人的工作,市售有一些链接库,专门做资料查核工作。
然而不要对MFC 的DDV 能力期望过高,稍后你就会看到,它只能满足最低层次的要
求而已。就DDV 而言,Borland 的OWL 表现较佳。
现在我打算以两个成员变量映射到对话框上的两个Edit 字段。我希望当使用者按下
【OK 】钮,第一个Edit 字段的内容自动储存到m_nThinWidth 变量中,第二个Edit 栏
位的内容自动储存到m_nThickWidth 变量中:
IDD_PEN_WIDTHS DIALOG 。。。 class CPenWidthsDlg : public CDialog
IDD_PEN_WIDTHS DIALOG 。。。 class CPenWidthsDlg : public CDialog
BEGIN {
BEGIN {
EDITTEXT IDC_THIN_PEN_WIDTH; 。。。 public:
EDITTEXT IDC_THIN_PEN_WIDTH; 。。。 public:
EDITTEXT IDC_THICK_PEN_WIDTH;。。。 int m_nThinWidth;
EDITTEXT IDC_THICK_PEN_WIDTH;。。。 int m_nThinWidth;
。。。 int m_nThickWidth;
。。。 int m_nThickWidth;
END };
END };
618
…………………………………………………………Page 681……………………………………………………………
10 MFC
第 章 與對話盒
下面是ClassWizard 的操作步骤(为对话框类别增加两个成员变量,并设定DDX / DDV):
进入ClassWizard,选择【Member Variables 】附页,再选择CPenWidthsDlg。
对话框中央部份有一大块区域用来显示控制组件与变量间的对映关系(见下一
页图)。
选择IDC_THIN_PEN_ WIDTH,按下【Add Variable。。。 】钮,出现对话框如下。
键入变量名称为m_nThinWidth 。
选择变量型别为int 。
按下【OK 】键, 于是ClassWizard 为CPenWidthsDlg 增加了一个变量
m_nThinWidth 。
在ClassWizard 对话框最下方(见下一页图)填入变量的数值范围,以为DDV
之用。
重复前述步骤,为IDC_THICK_PEN_WIDTH 也设定一个对应变量,范围也是
1~20。
619
…………………………………………………………Page 682……………………………………………………………
第篇 深入 MFC 程式設計
上述动作影响我们的程序代码如下:
class CPenWidthsDlg : public CDialog
{
// Dialog Data
//{{AFX_DATA(CPenWidthsDlg)
enum { IDD = IDD_PEN_WIDTHS };
int m_nThinWidth;
int m_nThickWidth;
//}}AFX_DATA
。。。
CPenWidthsDlg::CPenWidthsDlg(CWnd* pParent /*=NULL*/)
: CDialog(CPenWidthsDlg::IDD; pParent)
{
m_nThickWidth = 0;
m_nThinWidth = 0;
。。。
}
void CPenWidthsDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CPenWidthsDlg)
620
…………………………………………………………Page 683……………………………………………………………
10 MFC
第 章 與對話盒
DDX_Text(pDX; IDC_THIN_PEN_WIDTH; m_nThinWidth);
DDV_Mi