第六课——创建和使用控件

一、何为控件

  • 控件:在系统内部定义的用于和用户交互的基本单元。
  • 分类:Windows普通控件(如编辑框、列表框、组合框等)、MFC扩展控件、ActiveX控件
  • 常用控件:静态控件、按钮、编辑框、列表框、组合框、滚动条、旋转按钮控件、日期时间控件
  • 控件的优势:简化编程、完成常用的功能

 

二、创建控件

情形一:在对话框模板中用编辑器指定控件(常用)

情形二:调用MFC相应控件类的成员函数Create来创建

  • 补充:常用控件类有CStatic、CButton、CEdit、CListBox、CComboBox等。

  下面以情形二来创建一个按钮:基于对话框的应用程序Ex_Create→ClassView选项卡(右击CEx_CreateDlg类名)→Add Member Variable(变量类型为CButton,变量名为m_btnWnd)→双击OnInitDialog函数名转至其实现代码处→添加如下代码。

BOOL CEx_CreateDlg::OnInitDialog()
{
	CDialog::OnInitDialog();
    ...
    // TODO: Add extra initialization here
    m_btnWnd.Create("你好", WS_CHILD | WS_VISIBLE
					| BS_PUSHBUTTON | WS_TABSTOP,
					CRect(20, 20, 120, 40), this, 201);		 //创建
    CFont *font = this->GetFont();           //获取对话框的字体
    m_btnWnd.SetFont(font);                  //设置控件字体
    return TRUE;  // return TRUE  unless you set the focus to a control
}

分析一:

①由于OnInitDialog函数在对话框初始化时被调用,因此将对话框中的一些初始化代码都添加在此函数中。

②CButton类成员函数Create用来创建按钮控件。其第一个参数用来指定按钮的标题;第二个参数用来指定按钮控件的样式,其中BS_PUSHBUTTON(以BS_开头的)是按钮类封装的预定义样式,表示创建的是按键按钮;而WS_CHILD(子窗口)、WS_VISIBLE(可见)、WS_TABSTOP(可用Tab键选择)等都是CWnd类封装的预定义窗口样式,它们都可以直接引用;第三个参数用来指定它在父窗口中的位置和大小;第四个参数用来指定父窗口指针;最后一个参数指定该控件的标识值。

③由于按钮是作为对话框的一个子窗口来创建的,因此WS_CHILD样式是必不可少的,且还要使用WS_VISIBLE使控件在创建后显示出来。

④由于Windows操作系统使用的是图形界面,因此在MFC中,对于每种界面元素的几何大小和位置常使用CPoint类(点)、CSize类(大小)和CRect类(矩形)来描述。

分析二:

①控件编程创建方法是使用各自封装的类(即各控件类)的Create成员来创建。其优点是能动态创建(即运行时才创建控件),但它涉及的编程内容比较复杂,且不能发挥对话框编辑器可视化的优点。

②在MFC中,每一种类型的控件都用相应的类来封装。

 

三、控件的消息

  • 通知消息:当控件的状态发生改变时,控件就会向其父窗口发送消息,这个消息称为“通知消息”。

对于每个消息,系统都会用一个MSG结构来记录,MSG具有下列原型:

typedef struct tagMSG {         //msg
    HWND        hwnd;           //消息发向的(接收到消息的)窗口的句柄
    UINT        message;        //主消息的标识值
    WPARAM      wParam;         //附消息值,其具体含义依赖于主消息值
    LPARAM      lParam;         //附消息值,其具体含义依赖于主消息值
    DWORD       time;           //消息放入消息队列中时的时间
    POINT       pt;             //消息放入消息队列中时的鼠标坐标
}MSG;
  • 对于一般控件,其通知消息通常是一条WM_COMMAND消息,该消息的wParam参数的低位字中含有控件标识符,wParam参数的高位字则为通知代码,lParam参数则是指向控件的句柄
  • 而对于有些控件,其通知消息通常是一条WM_NOTIFY消息,该消息的wParam参数是发送通知消息的控件的标识符,而lParam参数则是指向一个结构指针

 

四、映射控件消息

  不管是什么控件消息,一般都可以用MFC ClassWizard对它们加以映射。

以一个标识符为IDC_BUTTON1的按键按钮为例:MFC ClassWizard对话框(Message Maps选项卡)→类名选定为CEx_CreateDlgObjects IDs选定为IDC_BUTTON1)→双击Messages列表框中的(要映射的)BN_CLICKED消息→在CEx_CreateDlg类中添加该消息的映射函数OnButton1→双击消息函数OnButton1定位到CEx_CreateDlg:: OnButton1代码实现处→添加如下代码→编译并运行。

void CEx_CreateDlg::OnButton1()
{
	// TODO: Add your control notification handler code here
    MessageBox(_T("你按下了\"Button1\"按钮!"));
}

说明:

①不同资源对象(控件、菜单命令等)所产生的消息是不同的。例如,按键按钮IDC_BUTTON1的消息有两个:BN_CLICKED和BN_DOUBLECLICKED,分别表示当用户单击或双击该按钮时产生的消息。

②不需要对对话框中的“确定”和“取消”按钮进行消息映射,因为系统已自动设置了这两个按钮的动作,当用户单击这两个按钮时都将自动关闭对话框,且确定按钮动作还使得对话框数据有效。

 

五、映射控件通用消息

上述过程是映射一个控件的某一个消息,事实上也可以通过WM_COMMAND消息的映射来处理一个或多个控件的通用消息

且以一个标识符为IDC_BUTTON1的按键按钮为例:MFC ClassWizard对话框(Message Maps选项卡)→类名选定为CEx_CreateDlgObjects IDs选定为CEx_CreateDlg)→双击Messages列表框中的(要映射的)OnCommand消息→在CEx_CreateDlg类中添加该消息的映射函数OnCommand→双击消息函数OnCommand定位到CEx_CreateDlg:: OnCommand代码实现处→添加如下代码→编译并运行。

BOOL CEx_CreateDlg::OnCommand(WPARAM wParam, LPARAM lParam)
{
	// TODO: Add your specialized code here and/or call the base class
    WORD nCode = HIWORD(wParam);		//控件的通知消息
    WORD nID = LOWORD(wParam);			//控件的ID号
	if ((nID == 201) && (nCode == BN_CLICKED))
		MessageBox(_T("你按下了\"你好\"按钮!"));
	if ((nID == IDC_BUTTON1) && (nCode == BN_CLICKED))
		MessageBox(_T("这是在OnCommand处理的结果!"));
	return CDialog::OnCommand(wParam, lParam);
}

说明:

①OnCommand函数是一个用来处理WM_COMMAND消息的虚函数,故而这里添加的OnCommand函数事实上是一个在类中实际调用的函数,可称为“实例函数”。这样的映射操作,可以称为“对虚函数OnCommand的重载”。

②在上述编写的代码中,Button1按钮的BN_CLICKED消息用不同的方式处理了两次,即同时存在两种函数OnButton1和OnCommand,故若单击Button1按钮,系统首先执行OnCommand函数,然后执行OnButton1代码。之所以还能执行OnButton1函数代码,是因为OnCommand函数的最后一句代码“return CDialog::OnCommand(wParam, lParam);”,它将控件的消息交由对话框其他函数处理。

③由于用Create创建的控件无法用MFC ClassWizard直接映射其消息,因此上述方法弥补了ClassWizard的不足,使用时要特别注意。

 

六、使用控件

  • 使用控件之前需获得该控件的类对象指针或映射一个对象,然后通过该指针或对象来引用其成员函数进行操作。

下表是MFC封装的常用控件类:表3.1

获取一个控件的类对象指针:通过CWnd类的成员函数GetDlgItem来实现

//GetDlgItem函数声明
CWnd* GetDlgItem(int nID) const;
void GetDlgItem(int nID, HWND *phWnd) const;

说明:

①nID:指定控件或子窗口的ID值

②第一个版本:通过函数来返回CWnd类指针

③第二个版本:通过函数形参phWnd来返回其句柄指针

  • 注:CWnd类(第三课有提及)是通用的窗口基类,故想要调用实际的控件类及其基类成员,要对返回值进行类型转换,如CButton *pBtn = (CButton*)GetDlgItem(IDC_BUTTON1);

 

七、控件对象

  • 控件变量:控件相关联的成员变量(在Member Variables选项卡添加)
  • 控件变量分为两种类型:用于操作的控件对象、用于存取的数据变量
  • 注:它们都是与控件或子窗口进行绑定,但MFC只允许每种类型仅绑定一次。

为了理解上述两种类型,下面看示例:基于对话框的应用程序Ex_Member→添加ID为IDC_BUTTON1的按钮控件和ID为IDC_EDIT1编辑框控件→MFC ClassWizard对话框(Member Variable选项卡)→类名选定为CEx_MemberDlg(Control IDs选定为IDC_BUTTON1)→单击Add Variable按钮(弹出Add Member Variable对话框)→成员变量名为m_btnWnd(类别项为Control)→MFC ClassWizard对话框(Member Maps选项卡)→为CexMemberDlg添加IDC_BUTTON1的BN_CLICKED消息映射函数OnButton1→添加如下代码。

void CEx_MemberDlg::OnButton1() 
{
	// TODO: Add your control notification handler code here
	CString strEdit;								//定义一个字符串
	CEdit *pEdit = (CEdit*)GetDlgItem(IDC_EDIT1);	//获取编辑框中的内容
	pEdit->GetWindowText(strEdit);
	strEdit.TrimLeft();
	strEdit.TrimRight();
	if (strEdit.IsEmpty())
		m_btnWnd.SetWindowText(_T("Button1"));		//将m_btnWnd的内容设定为按钮控件的标题
	else
		m_btnWnd.SetWindowText(strEdit);
}

说明:

成员变量m_btnWnd与控件IDC_BUTTON1相关联

②控件按钮IDC_BUTTON1的编程操作可用与之绑定的对象m_btnWnd来操作

     

八、DDXDDV技术

  • 概述:对于控件的数据变量MFC提供了DDXDDV技术。
  • DDX:将数据成员变量同对话类模板内的控件相联接(方便数据在控件间传输)
  • DDV:用于数据的校验

某控件与一个数据变量相绑定后,就可以用CWnd::UpdateData函数实现控件数据的输入和读取

UpdateData函数:只有一个参数,它为TRUEFALSE。当在程序中调用UpdateData(TRUE)或不带参数的UpdateData()时,数据从控件向相绑定的成员变量复制;反之,数据则由控件绑定的成员变量向控件传输。

说明:数据变量的类型由被绑定的控件类型而定。

使用示例(建立在项目Ex_Member的基础上):MFC ClassWizard对话框(Member Variable选项卡)→类名选定为CEx_MemberDlgControl IDs选定为IDC_EDIT1单击Add Variable按钮(弹出Add Member Variable对话框)成员变量名为m_strEdit(类别项为Value)→出现Maximum Characters编辑框(这就是控件变量的DDV设置)→ClassView选项卡(展开CEx_MemberDlg类结点)→双击OnButton1成员函数结点(定位到CEx_MemberDlg::OnButton1函数实现代码处)→改写如下代码。

void CEx_MemberDlg::OnButton1()
{
	// TODO: Add your control notification handler code here
    UpdateData();       //没有参数,表示使用的是默认参数值TRUE
    m_strEdit.TrimLeft();
    m_strEdit.TrimRight();
    if (m_strEdit.IsEmpty())
		m_btnWnd.SetWindowText(_T("Button1"));
	else
		m_btnWnd.SetWindowText(m_strEdit);
}

 

转载于:https://www.cnblogs.com/xzxl/p/7941751.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值