Click here to Skip to main content
15,889,851 members
Articles / Desktop Programming / MFC
Article

Localized numeric editbox

Rate me:
Please Sign up or sign in to vote.
4.08/5 (14 votes)
11 Aug 20031 min read 64.9K   2.3K   22   4
An article on extending edit box control

NumericEdit

Introduction

Microsoft provides to developers rich collection of GUI controls. The edit box control is very useful, but has one diasadvantage: it does not supports the numeric decimals. This article describes the creation of numeric edit box.

Background

The Microsoft's controls are localized. For example, if you change the local time format from the "Regional Options" dialog,

CDateTimeCtrl 
change it time format. The presented numeric edit box is localized as well. By the creation time it loads the locale decimal point delimiter and use it. Here is the code:

///
/// Constructor.
///
CNumericEdit::CNumericEdit()
{
    // determine the decimal delimiter buffer size    
    const int nBuffLen = ::GetLocaleInfo( LOCALE_USER_DEFAULT, 
        LOCALE_SDECIMAL, NULL, 0 );
    _ASSERT( nBuffLen > 0 );    

    // get the decimal number delimiter    
    const int nResult = ::GetLocaleInfo( LOCALE_USER_DEFAULT, 
        LOCALE_SDECIMAL, 
        m_strDelim.GetBuffer(nBuffLen), nBuffLen );
    _ASSERT(nResult != 0);
    m_strDelim.ReleaseBuffer();    
}</CODE>

Using the code

You should do following steps:

  1. Place the edit box control on the dialog.
  2. Assotiate the CEdit dialog class member to the edit box control.
  3. Include the "NumericEdit.h" to the your dialog class header.
  4. Replace the CEdit with CNumericEdit.
    //
    // Example of using the code
    //
    #include "NumericEdit.h"
    
    // some code
    
    protected:
        // some code
    	
        CNumericEdit m_editNumeric;
    	
        // some code

Points of Interest

Microsoft says about WM_SETTINGCHANGE :

The system sends the WM_SETTINGCHANGE message to all top-level windows when the SystemParametersInfo function changes a system-wide setting or when policy settings have changed.

I checked it, it works. Currently the numeric edit box control sets it's locale by creation time. It will be much better the control to react to operation system changes. But the WM_SETTINGCHANGE message is sent only to top-level windows, not to child windows. The possible solution is to handle the WM_SETTINGCHANGE in main window and delegate the WM_SETTINGCHANGE message to all child windows, but it seams ugly. I continue find other solution of this problem.

History

  • 12.08.2003 - First version of the code.

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


Written By
Web Developer
Bulgaria Bulgaria
I am a senior developer in Melon Technologies Ltd.

Comments and Discussions

 
GeneralMinor changes Pin
Terence Russell24-Mar-05 6:55
Terence Russell24-Mar-05 6:55 
GeneralRe: Minor changes Pin
Terence Russell24-Mar-05 7:06
Terence Russell24-Mar-05 7:06 
GeneralRe: Minor changes Pin
DeanV1-Feb-06 6:25
DeanV1-Feb-06 6:25 
This is a great little piece of code to handle numeric input, without all the masking! Thanks!

I couldn't get it to handle the delim correct when it was part of the selection, so ended up with this code over the last hr. or so. Seems to work perfect for me so far (when applyed to text property). Also able to take negative input ('-' for first char).

void CNumericEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
TCHAR delimiter = m_strDelim.GetAt(0);
int nStartChar, nEndChar;

if( nChar == (UINT) delimiter )
{

CString strText;
GetWindowText( strText );

if ( strText.IsEmpty() )
{
SetWindowText( (_T("0") + m_strDelim) );
SetSel( 2, 2, FALSE );
return;
}
else
{
// If the entire number is selected, replace it with a zero and the delimiter
BOOL delimSelected;
delimSelected = false;
GetSel(nStartChar, nEndChar);
if ( (nStartChar == 0) && (nEndChar == strText.GetLength()) )
{
// full replacement
SetWindowText( (_T("0") + m_strDelim) );
SetSel( 2, 2, FALSE );
return;
}
else if (nStartChar < nEndChar) { //some of it was selected
//look for delim in selection
int x;
x = nStartChar;
while (x <= nEndChar) {
if ( strText[x] == m_strDelim) {
delimSelected = true;
x = nEndChar; //force exit loop
}
x++;
}
}

// if the decimal point already entered, not allow enter more points
if( strText.Find( m_strDelim ) >= 0 && delimSelected == false)
return;

// no delimiter yet entered, so insert one //let the bottom take care of this.
// SetWindowText( (strText + m_strDelim) );
// int nNewLength = strText.GetLength() + m_strDelim.GetLength(); // delimiter might be more than one character?
// SetSel( nNewLength, nNewLength, FALSE );
// return;
}
}

// 8 - back space
// 46 - .
// 48 - 1
// 57 - 0
GetSel(nStartChar, nEndChar); //so we can check for '-' in first pos. only
if( (nChar == (UINT) delimiter) || (nChar >= '0' && nChar <= '9') || (nChar == 8)
|| (nChar == '-' && nStartChar == 0) )
{
CEdit::OnChar(nChar, nRepCnt, nFlags);
}
}

-- modified at 15:32 Wednesday 1st February, 2006
GeneralThe easy way to handle notifications Pin
ed welch13-Aug-03 0:26
ed welch13-Aug-03 0:26 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.