Я пытаюсь создать 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
или изменить мою программу, чтобы избежать рекурсии такого типа?
Я изменил выше 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
?
Спасибо за ваше время и помощь.
С наилучшими пожеланиями.
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..
Установите m_bSentFromSWT = FALSE в вашем WM_CREATE.