Как избежать рекурсии при ответе на сообщение EN_UPDATE

Я пытаюсь создать 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или изменить мою программу, чтобы избежать рекурсии такого типа?

РЕДАКТИРОВАТЬ (18 февраля 2014 г.):

Я изменил выше 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 сообщение при работе с текущим текстом, поэтому в приведенном выше примере я получаю результат bc вместо cc когда я нажимаю a а потом b?

Конец редактирования

Спасибо за ваше время и помощь.

С наилучшими пожеланиями.

0

Решение

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;
}
1

Другие решения

Попробуйте установить 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..

Установите m_bSentFromSWT = FALSE в вашем WM_CREATE.

0

По вопросам рекламы [email protected]