I am trying to create an edit control
that will accept signed decimal numbers in the format of sign number separator number ( e.g. -1.5
).
After extensive research on the Internet I have found few satisfying examples of masked edit controls, but they are done in MFC
.
Since I do not know MFC
, I have trouble translating that code into pure Win32 API
, so I have decided to try doing it my own way, starting from scratch.
After carefully studying the MFC
examples I have concluded that they perform text validation when responding to EN_UPDATE
message.
When I try to do the same my program exits immediately, without any warning or error message. I have concluded that my problem must be recursion.
To confirm this I have wrote a small handler in my main window's procedure to test this:
case WM_COMMAND:
switch( HIWORD( wParam ) )
{
case EN_UPDATE:
if( LOWORD(wParam) == IDC_OF_MY_EDIT_CONTROL)
{
static int counter = 0; // increment it each time we get EN_UPDATE
// after we receive EN_UPDATE 4 times stop testing
if( ( counter++) < 4 )
{
wchar_t text[10]; // get sample text
GetWindowText( (HWND)lParam, text, 10 );
// change current char to char + 1
// which means A will be B, B will be C and so on...
for( int i = 0; i < wcslen(text); i++ )
text[i] = (wchar_t)( 1 + text[i] );
SetWindowText( (HWND)lParam, text ); // show changed text
}
}
break;
}
break;
case WM_CLOSE: // WM_CLOSE and other handlers...
This is what happens when I start my program in Debug
mode:
After I type letter a
the text of the edit control turns into e
.
This confirms my conclusion about recursion: After I have pressed a
it was converted to b
, then another EN_UPDATE
fired off, which repeated the process so b
turned into c
and so on until static
variable reached 4
so the result was e
.
My question is simple:
How should I handle EN_UPDATE
, or modify my program, in order to avoid this type of recursion ?
I have modified the above EN_UPDATE
handler per member Jonathan Potter's instructions.
Although recursion problem disappeared, the output is not what I have desired.
I have verified the correctness of my code for substituting a character with his successor in a simple console application and by doing the same when clicking on a button ( it wasn't hard for me to quickly add a button and a handler for clicking on it ).
So the problem must be the implementation of the given instructions, therefore I submit the corrected code in hope that someone will point out what did I do wrong:
case EN_UPDATE:
if( LOWORD(wParam) == IDC_OF_MY_EDIT_CONTROL)
{
static bool OK_to_process_text = true;
if( OK_to_process_text )
{
OK_to_process_text = false;
wchar_t text[10];
memset( text, L'0', sizeof(text) );
GetWindowText( (HWND)lParam, text, 10 );
for( size_t i = 0; i < wcslen(text); i++ )
text[i] = (wchar_t)( 1 + text[i] );
SetWindowText( (HWND)lParam, text );
OK_to_process_text = true;
}
}
break;
}
break;
Now, after pressing a
it properly turns into b
, but after I press b
I do not get the expected result bc
but cc
.
This is expected, since after user presses a key EN_UPDATE
is generated to display text.
Therefore when pressing a
it will convert to b
. When I press b
afterwards, a new EN_UPDATE
message is generated, so my handler starts over, which means that it takes new string bb
and properly converts it to cc
.
Is there a way to suppress temporarily creation of a new EN_UPDATE
message while manipulating with current text so in the example above I get the result bc
instead of cc
when I press a
and then b
?
Thank you for your time and help.
Best regards.
I am trying to create an edit control that will accept signed decimal numbers in the format of sign number separator number ( e.g. -1.5 )
Maybe I am misunderstanding the situation, why not use EN_CHANGE and give the user a indication that the value is not correct, with something like the following?
[code below is for MS Visual Studio]
case EN_CHANGE:
if( LOWORD(wParam) == IDC_OF_MY_EDIT_CONTROL)
{ TCHAR szValue[32];
double dd;
GetWindowText((HWND)lParam, szValue, _countof(szValue));
if (_stscanf(szvalue, _T("%lf"), %dd) == 1)
{ // optionally reset an error indicator on the screen
}
else
{ MessageBeep(MB_ICONEXCLAMATION);
// optionally set an error indicator on the screen
}
break;
}