Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

The Ultimate Toolbox Masked Edit

0.00/5 (No votes)
25 Aug 2007 1  
The Ultimate Toolbox provides a generic masked edit control for validated input.

Visit the Ultimate Toolbox main page for an overview and configuration guide to the Ultimate Toolbox library.

Source code and project files for this sample can be found in the samples\gui\maskededit directory of the sample projects download.

Contents

Overview

The COXMaskedEdit control is an easy-to-use edit control that allows you to specify the format in which text entries will be made.

Features

The COXMaskedEdit control provides restricted data input as well as formatted data output. This control supplies visual cues about the type of data being entered or displayed.

COXMaskedEdit generally behaves as a standard text box control with enhancements for optional masked input and formatted output. If you don't use an input mask, it behaves much like a standard text box.

If you define an input mask, each character position in the COXMaskedEdit control maps to either a placeholder of a specified type or a literal character. Literal characters, or literals, can give visual cues about the type of data being used. For example, the parentheses surrounding the area code of a telephone number are literals: (206).

If you attempt to enter a character that conflicts with the input mask, the control generates a "ValidationError" beep. The input mask prevents you from entering invalid characters into the control. When you define an input mask, the Masked Edit control behaves differently from the standard text box. The insertion point automatically skips over literals as you enter data or moves the insertion point.

When you insert or delete a character, all non-literal characters to the right of the insertion point are shifted, as necessary. If shifting these characters leads to a validation error, the insertion or deletion is prevented, and a "ValidationError" beep is triggered. For example, suppose the Mask property is defined as "?###", and the current value of the Text property is "A12." If you attempt to insert the letter "B" to the left of the letter "A", the "A" would shift to the right. Since the second value of the input mask requires a number, the letter "A" would cause the control to generate a "ValidationError" beep.

COXMaskedEdit also validates the parameter value of the SetInputText function the user passes at run time. If you use the SetInputText function so that it conflicts with the input mask, the function will return an error code.

You may select text in the same way as for a standard text box control. When selected text is deleted, the control attempts to shift the remaining characters to the right of the selection. However, any remaining character that might cause a validation error during this shift is deleted, and no "ValidationError" beep is generated.

Normally, when a selection in the COXMaskedEdit control is copied onto the Clipboard, the entire selection, including literals, is transferred onto the Clipboard. You can use the SetClipMode function to define the behavior so that only the user-entered data is transferred onto the Clipboard - the literal characters that are part of the input mask are not copied.

Usage

You can attach a COXMaskedEdit to an existing CEdit control by subclassing the latter.

This is remarkably simple to do in the DevStudio IDE when working with an MFC dialog. Place a standard edit control on the dialog using the dialog editor. Invoke the Class Wizard and select the Member Variables page. Add a member variable for the ID of the edit control, selecting a CEdit control as the type.

Next, open the header file for the dialog. Include OXMaskedEdit.h. In the AFX_DATA section for the dialog you will see the declaration for the edit control as a CEdit. Change this to COXMaskedEdit (or a class derived from COXMaskedEdit) and viola - you can now initialize the mask etc. You won't need to call Create. (Don't forget to include the OXMaskedEdit.cpp file in your project!)

The samples\gui\maskededit sample demonstrates setting different masks.

#include "OXMaskedEdit.h"    // COXMaskedEdit


/////////////////////////////////////////////////////////////////////////////


// CMaskedEditTestDlg dialog


class CMaskedEditTestDlg : public CDialog
    {
    // Construction


    public:
        CMaskedEditTestDlg(CWnd* pParent = NULL) ;
        
        // Dialog Data


    protected:
        //{{AFX_DATA(CMaskedEditTestDlg)


    enum { IDD = IDD_MASKEDEDITTEST_DIALOG };
        COXMaskedEdit m_editMasked   ;
        CComboBox     m_comboMasks   ;
        CString       m_csPromptChar ;

If you want to be notified on validation of the data entered, you can add an ON_NOTIFY handler to the parent of the COXMaskedEdit - in this case the sample dialog:

BEGIN_MESSAGE_MAP(CMaskedEditTestDlg, CDialog)
    //{{AFX_MSG_MAP(CMaskedEditTestDlg)


    ...
    //}}AFX_MSG_MAP


    ON_NOTIFY(OXMEN_VALIDATE,IDC_EDIT_TEST,OnValidateEditTest)
END_MESSAGE_MAP()

And code a handler - this code from the sample just looks for "345" and will not allow the user to leave the control if found:

void CMaskedEditTestDlg::OnValidateEditTest(NMHDR * pNotifyStruct, 
    LRESULT * result)
{
    LPMENMHDR pMENotifyStruct = (LPMENMHDR)pNotifyStruct;

    UpdateData();

    CString sText=m_editMasked.GetInputData();

    // just as an example: if user typed "345" then typed 


    // information is invalid,


    // cursor will be set before first found "345" symbol


    int nPos=sText.Find(_T("345"));
    if(nPos!=-1)
    {
        pMENotifyStruct->bValid=FALSE;
        pMENotifyStruct->nPosition=m_editMasked.LPtoRP(nPos);
    }
    else
    {
        pMENotifyStruct->bValid=TRUE;
        pMENotifyStruct->bDefaultValidation=TRUE;
    }
    *result=0;
}

The OnInitDialog method in the sample adds some masks to the mask selection combo, then calls the OnSelendokMasks handler explicitly to set the first one as the mask for the COXMaskedEdit:

    m_comboMasks.AddString ( _T("Digit Test: ###-####") ) ;
    m_comboMasks.AddString ( _T("Decimal Test: ###.###.###.###") ) ;
    m_comboMasks.AddString ( _T("Thousands Test: ##,###.##") ) ;
    m_comboMasks.AddString ( _T("Time Test: ##:##") ) ;
    m_comboMasks.AddString ( _T("Date Test: ##/##/####") ) ;
    // Since the "C" programming language also uses the '\' as an 


    // escape character, you must use two in sequence to equal one 


    // switch for masking purposes. 


    m_comboMasks.AddString ( _T(
        "\\Alphanumeric Test: AAAAAAAAAA\\, AAAAAAAA") ) ;
    m_comboMasks.AddString ( _T(
        "\\Alphabetic Test: ????????????????") ) ;
    m_comboMasks.AddString ( _T(
        "Uppercase Test: >>>>>>> ????????") ) ;
    m_comboMasks.AddString ( _T(
        "Lowercase Test: <<<<<<< ????????") ) ;
    m_comboMasks.AddString ( _T("Phone:(###)###-#### Ext:####") ) ;
    m_comboMasks.AddString ( _T("AAA-#######")                  ) ;
    m_comboMasks.AddString ( _T(
        "&####-##-## ##\\:##\\:##")     ) ;
    m_comboMasks.SetCurSel ( 0 ) ;
    OnSelendokMasks() ;
void CMaskedEditTestDlg::OnSelendokMasks()
    {
    TRACE(_T("CMaskedEditTestDlg::OnSelendokMasks()\n"));

    int nSelected = m_comboMasks.GetCurSel() ;
    if ( nSelected >= 0 )
    {
        CString csNewMask ;
        m_comboMasks.GetLBText ( nSelected, csNewMask ) ;
        m_editMasked.SetMask   ( csNewMask ) ;
    }
}

Depending on the order of compilation you may also find if helpful to include OXMaskedEdit.h in the dialog and/or main application .cpp file of your project.

A full class reference for COXMaskedEdit is available in the compiled HTML help documentation.

History

Initial CodeProject release August 2007.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here