我正在尝试创建一个edit control
,它将接受符号号分隔符号格式的带符号十进制数(例如-1.5
)。
经过对互联网的广泛研究,我发现很少有令人满意的屏蔽编辑控件的例子,,但它们是在MFC
中完成的。
由于我不知道MFC
,我很难将该代码翻译成纯Win32 API
,所以我决定尝试用自己的方式从头开始。
在仔细研究了MFC
示例后,我得出结论,它们在响应EN_UPDATE
消息时执行文本验证。
当我尝试执行同样的操作时,我的程序立即退出,没有任何警告或错误消息。我已经得出结论,我的问题一定是递归。
为了证实这一点,我在主窗口的程序中编写了一个小的处理程序来测试:
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...
这就是当我在Debug
模式下启动程序时发生的情况:
在我键入字母a
之后,编辑控件的文本将变为e
。
这证实了我关于递归的结论:在我按下a
后,它被转换为b
,然后另一个EN_UPDATE
发射,它重复这个过程,所以b
变成c
,以此类推,直到static
变量到达4
,所以结果是e
。
我的问题很简单:
为了避免这种类型的递归,我应该如何处理EN_UPDATE
或修改我的程序?
编辑(2014年2月18日):
我已经根据成员Jonathan Potter的说明修改了上述EN_UPDATE
处理程序。
尽管递归问题消失了,但输出并不是我想要的。
我已经验证了我的代码的正确性,在一个简单的控制台应用程序中用他的继任者替换了一个字符,并在点击按钮时进行了同样的操作(我很难快速添加一个按钮和一个用于点击它的处理程序)。
因此,问题一定是给定指令的执行,因此我提交了更正后的代码,希望有人能指出我做错了什么:
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;
现在,在按下a
之后,它正确地变成了b
,但在我按下b
之后,我没有得到预期的结果bc
,而是cc
。
这是意料之中的,因为在用户按下按键之后生成EN_UPDATE
以显示文本。
因此,当按下a
时,它将转换为b
。当我随后按下b
时,会生成一条新的EN_UPDATE
消息,因此我的处理程序会重新启动,这意味着它会获取新的字符串bb
并将其正确转换为cc
。
有没有一种方法可以在使用当前文本进行操作时暂时禁止创建新的EN_UPDATE
消息,以便在上面的示例中,当我按下a
然后按下b
时,我得到的结果是bc
而不是cc
?
编辑结束
感谢您的时间和帮助。
致以最良好的问候。
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 )
也许我误解了这种情况,为什么不使用EN_CHANGE并向用户指示该值不正确,如下所示?
[以下代码适用于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;
}
尝试为编辑控件设置ES_MULTILINE。
或者
您可以在处理编辑控件通知之前检查标志。
case WM_COMMAND:
switch( HIWORD( wParam ) )
{
case EN_UPDATE:
if( LOWORD(wParam) == IDC_OF_MY_EDIT_CONTROL)
{
if (m_bSentFromSWT)
{
//No need to process this notification
m_bSentFromSWT = FALSE;
break;
}
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
m_bSentFromSWT = TRUE;
}
}
break;
}
break;
case WM_CLOSE: // WM_CLOSE and other handlers..
在WM_CREATE中设置m_bSentFromSWT=FALSE。
我确信这些年后,OP不可能使用MFC。
然而,对于任何遇到这个问题的人来说,最简单的解决方案是在消息处理程序的顶部有一个这样的块:
// Avoid Recursion
static bool updating = false;
if (updating)
{
updating = false;
return;
}
就在您在处理程序中调用SetWindowText之前,请设置updateing=true。它可能感觉有点难看,但它是MFC。