1

我正在尝试创建一个edit control将接受符号数字分隔符格式的带符号十进制数字(例如-1.5)。

在 Internet 上进行广泛研究后,我发现很少有令人满意的蒙版编辑控件示例,但它们是在MFC.

因为我不知道MFC,所以我很难将该代码翻译成 pure 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模式下启动程序时发生的情况:

在我输入 letter 后a,编辑控件的文本变成e.

这证实了我关于递归的结论:在我按下a它之后它被转换为b,然后另一个EN_UPDATE被触发,它重复了这个过程,所以b变成了c等等,直到static变量达到4所以结果是e

我的问题很简单:

EN_UPDATE为了避免这种类型的递归,我应该如何处理或修改我的程序?

编辑(2014 年 2 月 18 日):

EN_UPDATE我已按照成员Jonathan Potter的说明修改了上述处理程序。

虽然递归问题消失了,但输出不是我想要的。

我已经验证了我的代码在一个简单的控制台应用程序中用他的继任者替换一个字符的正确性,并且在单击一个按钮时也这样做(我不难快速添加一个按钮和一个处理程序来单击它)。

所以问题一定是给定指令的执行,因此我提交了更正的代码,希望有人能指出我做错了什么:

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新消息,所以在上面的示例中,我得到结果bc而不是cc按下a然后b

编辑结束

感谢您的时间和帮助。

此致。

4

2 回答 2

1

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;
    }
于 2014-02-18T13:36:24.517 回答
0

尝试为您的编辑控件设置 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。

于 2014-02-18T10:48:06.503 回答