VC编程之白乔原创:VC之控件篇
小标 2019-04-26 来源 : 阅读 535 评论 0

摘要:本文主要向大家介绍了VC编程之白乔原创:VC之控件篇,通过具体的内容向大家展示,希望对大家学习VC编程有所帮助。

本文主要向大家介绍了VC编程之白乔原创:VC之控件篇,通过具体的内容向大家展示,希望对大家学习VC编程有所帮助。

VC编程之白乔原创:VC之控件篇

1 使用Windows标准控件


1.1 常见控件列表


Windows标准控件即普通控件,撰写此文时,笔者每天面对的Word就带了一脸的控件,当然你肯定也熟悉:字体选择下拉框、工具栏、滚动条、状态栏,如此等等。


常见的Windows标准控件在VC里就有:


图2 控件集窗口


通常这个控件集窗口在你的对话框设计界面的附近总能找到,如果找不到,在VC工具栏的任何空白处点击右键,在弹出菜单的Controls菜单项前面打上勾即可,如图所示:


图3 显示控件集窗口


你也许已经看到了,我们图1所示的FlashPlayer中有3个控件是Windows标准控件,好,我们先系统地学习一下怎么使用这3个控件。


1.2 引入控件


1. 准备对话框


对话框相当于控件的容器,我们当然要先准备一个对话框。好办,直接创建一个基于对话框的工程就是了:


图4 准备对话框Step 1


注意,在Step 2中要确认“3D Controls”和“ActiveX Controls”前面打上勾,如图所示:


图5 准备对话框Step 2


这样你的程序就支持三维控件和我们后面即将使用到的ActiveX控件了。如果去掉了勾,或者你面对的正是你师兄当年准备论文的旧的
project,它好像并不支持ActiveX控件,那该怎么办呢(好多VC网友总是带着那张哭丧脸的表情问我这种问题)?没事,在主程序文件的
InitInstance()函数头部加上以下语句即可:


查看源代码拷贝至剪贴板打印代码


BOOL CFlashPlayerApp::InitInstance()   

{   

    AfxEnableControlContainer();   

  

#ifdef _AFXDLL   

    Enable3dControls();         // Call this when using MFC in a shared DLL   

#else   

    Enable3dControlsStatic();   // Call this when linking to MFC statically   

#endif   

  

//…   

}   


BOOL CFlashPlayerApp::InitInstance()<br/>{<br/> AfxEnableControlContainer();<br/>#ifdef _AFXDLL<br/> Enable3dControls();   // Call this when using MFC in a shared DLL<br/>#else<br/> Enable3dControlsStatic(); // Call this when linking to MFC statically<br/>#endif<br/>//…<br/>}<br/>


对话框准备好了,缺省情况下,它总会自动带上3个控件:2个按钮,“确定”与“取消”和一个“TODO: 在这里设置对话控制” 文本标签。


2. 准备文本编辑框


文本标签我们并不需要,那么就直接删除之。但我们需要一个文本编辑框,用以显示Flash文件路径。引入新的Windows标准控件很简单,只要简单地从控件集窗口选择相应的控件拖拽至对话框即可。好,我们拖来一个文本编辑框:


图6 引入文本编辑框控件


1.3 设置控件属性


引入来的控件,可以通过鼠标简单的拖拽调整其位置和大小,当然,你还可以通过属性对话框来设计这个控件。在控件上右击鼠标,弹出菜单:


图7 控件的属性窗口


这个菜单即将覆盖本教程的大部分内容,菜单最下面的三行分别为:


ClassWizard… 为控件创建类及变量


Events… 为控件映射事件


Properties 设置控件的属性


前两项后面的内容将要讨论到,我们现在只关心Properties(属性),点击它即可弹出文本编辑框的属性界面:


图8 文本编辑框的属性界面


我们按照以下的步骤进行控件的属性设置:


1. 在“General(普通)”标签页里将文本编辑框的ID修改成IDC_FLASH_FILE,而不是缺省的IDC_STATIC;


2. 在“Styles(样式)”标签页里将文本编辑框的Read-only打勾,这样我们的文本编辑框就显示成灰色,并且只读。也就是说,它的,内容只能由程序更改,用户不能手动输入;


3. 同理,在两个按钮的“General(普通)”标签页里,设置它们的Caption(标题),分别为“浏览…”和“退出”;


4. 在“浏览…”按钮的“General(普通)”标签页里,将它的ID设置成ID_BROWSER;


需要指出的是,每个控件都具有ID,就相当于每个人都具有一个身份证号。除了IDC_STATIC(它的值是-1),每个对话框的控件的ID都必须
唯一,不能重复。一些特定的ID代表特定的含义,如:IDOK对应于“确定”按钮,IDCANCEL对应于“取消”按钮,IDC_STATIC则对应于一
个匿名控件。MFC认识这些特定的ID,并赋值于指定的行为,例如:你可以不需要编写任何代码,就可以使用“确定”按钮关闭对话框,就是这个原因。


以上内容指引你如何修改控件的属性,包括它的ID、标题以及样式。这种修改都是所见即所得的,运行程序,你就会欣喜地发现,一切确实都改过来了。


1.4 映射控件变量


好了,你现在有了一个文本编辑框,可是如何使用它,你还是一无所知。那么,我们开始学习如何将控件映射成一个变量,这个过程即“映射控件变量”,或曰“绑定控件变量”。


映射控件变量是VC的一个很好的功能,有了它,你就可以象使用一个变量一样控制控件。映射成什么类型的变量,这依赖于你的控件。一般来说,一个控件
可以映射成一个值变量(Value),也可以映射成一个控件对象(Control)。如:一个文本编辑框既可以映射成一个CString值,也可以映射成
一个CEdit对象,CString是个字符串,而CEdit则是MFC为文本编辑框专门准备的控件类。


1.4.1 控件 -> 值变量


我们从简单的入手,先将我们的文件路径文本编辑框映射成一个普通的值变量,按照以下操作慢慢来:


1. 在编辑框上打开右键菜单(如图7所示),选择ClassWizard…,弹出以下界面:


图9 ClassWizard窗口


有点晕。先不管别的,因为我们要映射变量,我们就选择“Member Variables”标签页, 这儿可以看到当前对话框中的所有控件,包括我们的文本框和其它两个按钮;


2. 找到我们的IDC_FLASH_FILE,双击之(或者点击“Add Variable…”按钮),就弹出了映射控件变量窗口:


图10 添加控件值变量


该界面分别要求输入变量名、类别和变量类型,不用争了,我们选择Value和CString,将IDC_FLASH_FILE映射成CString m_sFilePath。


大功告成!可以同时观察VC程序代码中的变化:


查看源代码拷贝至剪贴板打印代码


class CFlashPlayerDlg : public CDialog   

{   

// …   

// Dialog Data   

    //{{AFX_DATA(CFlashPlayerDlg)   

    enum { IDD = IDD_FLASHPLAYER_DIALOG };   

    CString m_sFilePath;   

    //}}AFX_DATA   

}   

  

CFlashPlayerDlg::CFlashPlayerDlg(CWnd* pParent /*=NULL*/)   

: CDialog(CFlashPlayerDlg::IDD, pParent)   

{   

    //{{AFX_DATA_INIT(CFlashPlayerDlg)   

    m_sFilePath = _T("");   

    //}}AFX_DATA_INIT   

    // …   

}   

  

void CFlashPlayerDlg::DoDataExchange(CDataExchange* pDX)   

{   

    CDialog::DoDataExchange(pDX);   

    //{{AFX_DATA_MAP(CFlashPlayerDlg)   

    DDX_Text(pDX, IDC_FLASH_FILE, m_sFilePath);   

    //}}AFX_DATA_MAP   

}   


class CFlashPlayerDlg : public CDialog<br/>{<br/>// …<br/>// Dialog Data<br/> //{{AFX_DATA(CFlashPlayerDlg)<br/> enum { IDD = IDD_FLASHPLAYER_DIALOG };<br/> CString m_sFilePath;<br/> //}}AFX_DATA<br/>}<br/>CFlashPlayerDlg::CFlashPlayerDlg(CWnd* pParent /*=NULL*/)<br/>: CDialog(CFlashPlayerDlg::IDD, pParent)<br/>{<br/> //{{AFX_DATA_INIT(CFlashPlayerDlg)<br/> m_sFilePath = _T("");<br/> //}}AFX_DATA_INIT<br/> // …<br/>}<br/>void CFlashPlayerDlg::DoDataExchange(CDataExchange* pDX)<br/>{<br/> CDialog::DoDataExchange(pDX);<br/> //{{AFX_DATA_MAP(CFlashPlayerDlg)<br/> DDX_Text(pDX, IDC_FLASH_FILE, m_sFilePath);<br/> //}}AFX_DATA_MAP<br/>}<br/>


下面我们先试试这个CString m_sFilePath的使用,如:


查看源代码拷贝至剪贴板打印代码


BOOL CFlashPlayerDlg::OnInitDialog()   

{   

    CDialog::OnInitDialog();   

    m_sFilePath = "空即是色";   

    // …   

}  


BOOL CFlashPlayerDlg::OnInitDialog()<br/>{<br/> CDialog::OnInitDialog();<br/> m_sFilePath = "空即是色";<br/> // …<br/>}


遗憾的是,以上的代码是没用的!与Visual Basic不同,在VC的世界里,映射的值变量与实际控件的内容并不保持同步,欲使用映射的值变量就必须额外地使用到UpdateData()函数,它的函数原型如下:


查看源代码拷贝至剪贴板打印代码


CWnd::UpdateData   

BOOL UpdateData( BOOL bSaveAndValidate = TRUE );  


CWnd::UpdateData<br/>BOOL UpdateData( BOOL bSaveAndValidate = TRUE );


简单地说,UpdateData(TRUE)读取对话框中各控件的内容,并及时反映到其映射值中去;UpdateData(FALSE)则恰恰相反,它将当前映射值反映到控件中去,如:在文本框里面显示你刚刚设置的字符串“空即是色”。


我们现在是要通过变量修改控件,因此,我们采用UpdateData(FALSE),以上的代码修改成:


查看源代码拷贝至剪贴板打印代码


BOOL CFlashPlayerDlg::OnInitDialog()   

{   

    CDialog::OnInitDialog();   

    m_sFilePath = "请点击“浏览”按钮选择文件!";   

    UpdateData(FALSE);   

    // …   

}  


BOOL CFlashPlayerDlg::OnInitDialog()<br/>{<br/> CDialog::OnInitDialog();<br/> m_sFilePath = "请点击“浏览”按钮选择文件!";<br/> UpdateData(FALSE);<br/> // …<br/>}


现在的运行界面就可以看到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   

}   


void CFlashPlayerDlg::DoDataExchange(CDataExchange* pDX)<br/>{<br/> CDialog::DoDataExchange(pDX);<br/> //{{AFX_DATA_MAP(CFlashPlayerDlg)<br/> DDX_Control(pDX, IDC_FLASH_FILE, m_FilePathEdit);<br/> DDX_Text(pDX, IDC_FLASH_FILE, m_sFilePath);<br/> //}}AFX_DATA_MAP<br/>}<br/>


DDX_Control标明控件IDC_FLASH_FILE与m_FilePathEdit映射,接下来,我们就可以通过使用CEdit类来控制文本编辑框控件,如图所示:


图14 使用CEdit变量修改控件内容


这时候,使用如下代码同样可以达到设置编辑框内容的效果:


查看源代码拷贝至剪贴板打印代码


m_FilePathEdit.SetWindowText("请点击“浏览”按钮选择文件!");  


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       

}   


BEGIN_MESSAGE_MAP(CFlashPlayerDlg, CDialog)<br/> //{{AFX_MSG_MAP(CFlashPlayerDlg)<br/> ON_WM_SYSCOMMAND()<br/> ON_WM_PAINT()<br/> ON_WM_QUERYDRAGICON()<br/> ON_BN_CLICKED(ID_BROWSER, OnBrowser)<br/> //}}AFX_MSG_MAP<br/>END_MESSAGE_MAP()<br/>void CFlashPlayerDlg::OnBrowser() <br/>{<br/> // TODO: Add your control notification handler code here <br/>}<br/>


4. 我们现在就可以修改这个OnBrowser()的代码,以实现我们需要的操作,既然我们希望它弹出一个选择文件的对话框,那么我们就这么写:


查看源代码拷贝至剪贴板打印代码


void CFlashPlayerDlg::OnBrowser()    

{   

    //文件对话框   

    CFileDialog FileDialog(true, ".swf", "", OFN_EXPLORER,   

        "Flash动画文件(*.swf)|*.swf|所有文件(*.*)|*.*||", this);   

  

    //显示对话框   

    if(FileDialog.DoModal() == IDOK)   

    {   

        m_sFilePath = FileDialog.GetPathName();   

        UpdateData(FALSE);   

    }   

}   


void CFlashPlayerDlg::OnBrowser() <br/>{<br/> //文件对话框<br/> CFileDialog FileDialog(true, ".swf", "", OFN_EXPLORER,<br/>  "Flash动画文件(*.swf)|*.swf|所有文件(*.*)|*.*||", this);<br/> //显示对话框<br/> if(FileDialog.DoModal() == IDOK)<br/> {<br/>  m_sFilePath = FileDialog.GetPathName();<br/>  UpdateData(FALSE);<br/> }<br/>}<br/>


呵呵,是不是又注意到UpdateData(FALSE)了?没错,将变量赋值了,就应该调用UpdateData(FALSE)将值反映出来。现在我们的运行界面可以选择文件了:


图18 事件响应函数OnBrowser()的实现


添加事件处理还有一种方法,就是使用我们前面熟悉到的ClassWizard窗口,打开“Message Maps(消息映射)”标签页,即可管理我们的控件消息:


图19 使用ClassWizard窗口管理消息映射


1.6 控件子类化


尽管Windows系统提供了各种丰富的控件,但总会有美中不足的时候。你是否注意到了?我们现在的文本框远没有FlashPlayer成品中的好看。FlashPlayer中的文本框黑底绿字,那叫一个酷!


那么我们就准备在原有文本编辑框的基础上再做一些定制,解决的办法是控件的子类化。


子类化是应用于窗口的高级技术,当然就可以应用于控件。子类化其原理就在于它修改了窗口(控件)的类内存块,这样既有窗口(控件)就不知不觉地修改了自己的模样和行为。


得益于控件的变量映射机制,在VC里,子类化控件并不是一件很难的事情。具体操作就是:为控件准备一个新类,例如CCoolEdit。一般这些类都
从某个原有的MFC类(如:CEdit)继承而来,这样它就可以很方便地继承基类的模样和行为;接下来的工作,就是我们将控件映射成这个新的
CCoolEdit,完全如同CEdit一样。


就这么简单,我们仔细走走看:


1. 准备子类;


已经有很好的CEdit类,既然我们要改造它,那就直接继承它:


以上就介绍了VC/MFC的学习,希望对VC/MFC有兴趣的朋友有所帮助。了解更多内容,请关注职坐标编程语言VC/MFC频道!


本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程