当前位置:C++技术网 > 精选软件 > 重载CEdit实现金额数字框,允许输入数字和小数点

重载CEdit实现金额数字框,允许输入数字和小数点

更新时间:2016-10-19 20:17:14浏览次数:1+次

    重载CEdit实现金额数字框,支持0-9和小数点的输入。金额数字框非常常用,使用默认的数字编辑框无法满足效果,所以需要自己重载实现。

    最终的效果是这样的:

重载CEdit实现金额数字框

   在金额数字框中,我们需要除了0-9外的小数点,甚至是包含逗号。如果我们在编辑框属性中将编辑框设置为数字框,设置位置:

编辑框属性中将编辑框设置为数字框

    设置后的数字框效果是这样的:

默认的数字编辑框

    当你输入小数点以及其他字符时,就会提示你不接受的字符。这个是不能满足我们需要的。所以我们要重载CEdit来实现我们需要的金额数字框。

    如果你对重载控件不熟悉,那么可能会有点恐惧,听到重载控件,似乎很难的样子。毕竟我以前也是这样想的。那么现在我将这个重载的过程分享出来,让更多人能够上手学会。

    在MFC中,我们可以给一个控件绑定一个变量,这样就可以直接用这个控件变量来操作控件了。而绑定编辑框控件的控件类为CEdit。CEdit类只包装了最基本的操作,而且CEdit是基础的类,MFC预先提供好了,我们就不好在这个类里面进行编辑框控件消息的响应。因为我们要定制编辑框,实现金额数字框,就需要对控件的消息进行独立的处理。所以,我们重载控件,也就是指定一个自定义的控件类,并用这个控件类来定义控件变量。这样,控件的消息因为关联到了我们写的控件类,所以,控件的消息都可以在我们的控件类中完成,因此也就可以定制控件的行为了。金额数字框的行为就是接受数字和小数点。这就是我们要的行为,我们进行消息处理就可以定制了。

    那么实现的步骤如下:

1.在对话框上拖一个编辑框上去,然后右击编辑框,点击“添加变量”,弹出对话框,一般情况,我们就是像下图这样添加变量的:

在对话框上拖一个编辑框上去,然后右击编辑框,点击“添加变量”,弹出对话框

    我们一般只要填写变量名即可,可以使用默认的变量类型CEdit。我们知道,默认的CEdit并不能实现金额数字框。不过因为我们还没有写好自己的编辑框类,所以这里就用默认的变量类型。回头再将变量m_edit的类型改为我们自己创建的编辑框控件类即可。点击完成按钮。

    如果你觉得用向导有时候不方便,你也可以直接在代码中添加。先在头文件中添加控件变量的声明:


public:
    CEdit m_edit;
    然后在源文件CPP文件中添加变量绑定:



void 对话框类名::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_EDIT1, m_edit);//添加的控件绑定
}
    这个函数是自动生成的,你只需要添加DDX_Control即可。绑定的参数里,第二个填写控件的ID,第三个就是在头文件声明的变量。这样写好后,编辑框控件就和CEdit的变量m_edit绑定起来了。当你自己的编辑框控件类CMoneyEdit写好后,将头文件的CEdit替换为CMoneyEdit即可。而编辑框的行为,全部在CMoneyEdit类内部写好。


2.创建编辑框控件类CMoneyEdit

    在类视图中添加类,如下图所示:

在类视图中添加类

    因为你要重载的是MFC的CEdit类,所以在弹出的对话框中选择“MFC类”,如下图所示:

因为你要重载的是MFC的CEdit类,所以在弹出的对话框中选择“MFC类”

    如果是添加纯C++的类,就选择C++类,只要是用到了MFC的类,或者继承自MFC的类,就选择MFC类。我们这里就是要继承CEdit类。

3.填写要添加的类信息

    选择了MFC类之后,点击右下角的“添加”按钮,弹出添加的类信息的对话框,如下图所示:

填写要添加的类信息

   我们填写自己的类名,这个类名就是自定义的编辑框控件类类名,后面要替换CEdit。基类就是我们要继承的CEdit类。我们所说的重载控件,其实就是重载CEdit的虚成员函数,CEdit是CMoneyEdit的父类。我们重载了CEdit的成员函数,那么编辑框的行为就按照我们的类CMoneyEdit而执行了。点击右下角的“完成”按钮,完成添加。可以看到,向导会自动帮我们创建好文件和基本的构造和析构函数。

4.编写CMoneyEdit类代码

    向导为我们创建好的类的头文件如下:


#pragma once
// CMoneyEdit
class CMoneyEdit : public CEdit
{
	DECLARE_DYNAMIC(CMoneyEdit)

public:
	CMoneyEdit();
	virtual ~CMoneyEdit();

protected:
	DECLARE_MESSAGE_MAP()
};
   源文件代码如下:



// MoneyEdit.cpp : 实现文件
//
#include "stdafx.h"
#include "tmp_edit.h"
#include "MoneyEdit.h"
// CMoneyEdit
IMPLEMENT_DYNAMIC(CMoneyEdit, CEdit)
CMoneyEdit::CMoneyEdit()
{
}
CMoneyEdit::~CMoneyEdit()
{
}
BEGIN_MESSAGE_MAP(CMoneyEdit, CEdit)
END_MESSAGE_MAP()
// CMoneyEdit 消息处理程序


    如果你不想用向导,那么你可以按照这个代码自己写。是一样的效果。

    下面是关键了,请仔细看了。

    我们要规定的行为就是,只能输入0-9和小数点,一共11个字符,其他都不能输入。也就是在按下每一个按键的时候,我们就需要对输入的字符进行检测,如果是这11个字符的一个,就允许输入,如果不是,则不允许输入。

    那么这个代码写在哪里呢?我们很容易想到,内容变化的事件EN_CHANGE,然而这里并不合适。我们是要逐个字符的过滤,内容变化并不太好应对。比如一次性来了好几个字符,作为一次内容变化,我们就需要每一个字符去检测。这个方法暂时放弃。

    再想一下,我们可能会想到WM_KEYDOWN消息。这个确实是一个按键一个消息,挺好。不过,因为WM_KEYDOWN消息偏重于按键本身,所以携带了很多非字符相关的信息,对我们这个不是最好的选择。

    而最好的选择就是WM_CHAR消息了。这个消息就是逐个的字符消息了。而且WM_CHAR是针对字符消息而设立的,自然是最好的选择了。我们就用这个消息来处理。

    也就是说,我们只要给金额数字框控件类CMoneyEdit添加一个WM_CHAR消息处理,就可以达到字符过滤的效果了。

    然而,新手习惯了在可视化的界面用向导添加消息处理,而我们自己添加的控件类,似乎不知道在哪去启动向导了。没事,我告诉你。在类视图中,右击CMoneyEdit,然后可以看到“类向导”,如下图所示:

在类视图中,右击类CMoneyEdit,然后可以看到“类向导”

   启动类向导后,就和资源视图中启动的类向导一样了。然后在消息中添加一个WM_CHAR的消息处理就行了。添加了WM_CHAR消息处理后,处理函数代码就自动添加了。如果你想手动添加消息处理函数,可以看下面的说明。

    在类CMoneyEdit的头文件中添加代码:


public:
    afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
    也就是添加了WM_CHAR消息的处理函数声明。afx_msg表示的是消息处理函数,和普通函数不一样,因为有消息映射。


    在类CMoneyEdit的源文件中向导添加的代码如下:

BEGIN_MESSAGE_MAP(CMoneyEdit, CEdit)
    ON_WM_CHAR()//向导添加WM_CHAR消息处理映射
END_MESSAGE_MAP()
// CMoneyEdit 消息处理程序
void CMoneyEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值
    CEdit::OnChar(nChar, nRepCnt, nFlags);
}
    你可以手动添加,也就是消息处理函数声明、消息映射、消息处理函数定义。


5.写金额数字框的过滤代码

   过滤代码就在消息处理函数中写,即在CMoneyEdit::OnChar内写。代码如下:

void CMoneyEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
    //允许输入的字符
    if (nChar=='.' || (nChar<='9'&&nChar>='0') || nChar=='\b' || nChar==127)
    {
        CEdit::OnChar(nChar, nRepCnt, nFlags);//允许输入字符
    }
    //不做处理,即输入无效
}
    可以看到,过滤本身的代码是非常简单的。如果允许输入,即调用CEdit的OnChar函数处理一下即可。如果不允许输入,不调用即可。


    这样就实现了最开始看到的金额数字框。就这么简单。