CWnd::UpdateData BOOL UpdateData( BOOL bSaveAndValidate = TRUE );
简单地说,UpdateData(TRUE)读取对话框中各控件的内容,并及时反映到其映射值中去;UpdateData(FALSE)则恰恰相反,它将当前映射值反映到控件中去,如:在文本框里面显示你刚刚设置的字符串“空即是色”。 我们现在是要通过变量修改控件,因此,我们采用UpdateData(FALSE),以上的代码修改成: BOOL CFlashPlayerDlg::OnInitDialog() { CDialog::OnInitDialog();
m_sFilePath = \请点击“浏览”按钮选择文件!\UpdateData(FALSE); // … }
现在的运行界面就可以看到m_sFilePath的内容了:
图11 使用映射变量修改文本编辑框的内容
UpdateData ()如何知道哪些控件与哪些变量映射,靠的是DoDataExchange(),读者没必要对DoDataExchange()了解更多,但注意不要随便手动修改DoDataExchange()中的代码。 1.4.2 控件 -> 控件对象
与值变量不同,如果映射变量是一个控件对象,那么就没有必要调用UpdateData ()来完成同步。将一个控件映射成控件对象也很简单,依2.4.1的步骤而行,同样弹出添加变量窗口:
图12 添加控件对象变量 注意在Category(类别)一栏选择Control,变量类型别无选择,选择CEdit,点击OK。这样我们的IDC_FLASH_FILE即有了2个映射变量:
图13 同时为控件绑定值变量和对象变量 同样地,以上的映射亦体现在代码里:
void CFlashPlayerDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CFlashPlayerDlg)
DDX_Control(pDX, IDC_FLASH_FILE, m_FilePathEdit); DDX_Text(pDX, IDC_FLASH_FILE, m_sFilePath); //}}AFX_DATA_MAP }
DDX_Control标明控件IDC_FLASH_FILE与m_FilePathEdit映射,接下来,我们就可以通过使用CEdit类来控制文本编辑框控件,如图所示:
图14 使用CEdit变量修改控件内容
这时候,使用如下代码同样可以达到设置编辑框内容的效果: m_FilePathEdit.SetWindowText(\请点击“浏览”按钮选择文件!\
相比而言,使用控件对象,可以最大限度地控制控件;但是,谁都知道,使用一个对象的步骤比操纵一个变量要麻烦得多。
删除控件变量并不需要任何技巧,在ClassWizard窗口选定该变量,点击“Delete Variable”即可。为了配合后续教程,我们先删掉这个CEdit m_FilePathEdit,在2.6节,我们将要把这个文本编辑框映射成我们自定义的类型。 1.5 响应控件事件
控件都是一个个的窗口,所以控件都有事件。最简单的,按钮被鼠标按下时,将产生BN_CLICKED事件。 那好,就响应“浏览”按钮的BN_CLICKED事件: 1. 弹出右键菜单(如图7所示),选择“Events…”,弹出如下窗口:
图15 控件事件窗口
窗口主要分成3部分:左侧为当前控件的所有消息列表,右上侧为已响应的消息,右下侧为当前窗口所有的控件列表(包括窗口本身)。注意到我们的“浏览”按钮现在还没有任何已响应的消息。
2. 双击左侧的“BN_CLICKED”(或者点击右边的“Add Handler”按钮),即弹出如下窗口,提示为响应函数取个名字:
图16 为事件响应函数命名
响应函数的名字一般皆以On打头,缺省的名字OnBrowser就蛮好,点击“OK”。 可以看到,现在我们的事件窗口已经包含了这个BN_CLICKED:
图17 已添加事件响应
3. 选择BN_CLICKED事件点击Edit Existing(也可以在上一步即点击Add and Edit),即可观察到代码中已增加以下内容:
BEGIN_MESSAGE_MAP(CFlashPlayerDlg, CDialog) //{{AFX_MSG_MAP(CFlashPlayerDlg) ON_WM_SYSCOMMAND() ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(ID_BROWSER, OnBrowser) //}}AFX_MSG_MAP END_MESSAGE_MAP() void CFlashPlayerDlg::OnBrowser() {
// TODO: Add your control notification handler code here }
4. 我们现在就可以修改这个OnBrowser()的代码,以实现我们需要的操作,既然我们希望它弹出一个选择文件的对话框,那么我们就这么写:
void CFlashPlayerDlg::OnBrowser()
{ //文件对话框
CFileDialog FileDialog(true, \动画文件(*.swf)|*.swf|所有文件(*.*)|*.*||\ //显示对话框 if(FileDialog.DoModal() == IDOK)
{ m_sFilePath = FileDialog.GetPathName(); UpdateData(FALSE); } }
呵呵,是不是又注意到UpdateData(FALSE)了?没错,将变量赋值了,就应该调用UpdateData(FALSE)将值反映出来。现在我们的运行界面可以选择文件了:
图18 事件响应函数OnBrowser()的实现
添加事件处理还有一种方法,就是使用我们前面熟悉到的ClassWizard窗口,打开“Message Maps(消息映射)”标签页,即可管理我们的控件消息:
图19 使用ClassWizard窗口管理消息映射 1.6 控件子类化
尽管Windows系统提供了各种丰富的控件,但总会有美中不足的时候。你是否注意到了?我们现在的文本框远没有FlashPlayer成品中的好看。FlashPlayer中的文本框黑底绿字,那叫一个酷!
那么我们就准备在原有文本编辑框的基础上再做一些定制,解决的办法是控件的子类化。 子类化是应用于窗口的高级技术,当然就可以应用于控件。子类化其原理就在于它修改了窗口(控件)的类内存块,