princektd Ответов: 1

Странное поведение при вводе с помощью IME в windows 10 1709


Я столкнулся с проблемой в Windows 10 Creators update, где, когда я пытаюсь ввести что-то в свое приложение с помощью IME, первый символ игнорируется; то есть, если я использую IME для ввода японского символа хираганы "DK", набрав K & A, я в конечном итоге получаю только "あ" с потерянным K. Это происходит только с первым персонажем. Но точно такое же приложение работает правильно в Windows 7~8.

Подробности приведены ниже:

Приложение представляет собой приложение MFC MDI типа контейнер/сервер. Его работа действительно проста и понятна. Если документ открыт, то при запуске WM_KEYDOWN динамически создайте поле CEdit и введите нажатую клавишу в поле редактирования. Если поле редактирования уже существует, нет необходимости создавать его снова. Просто добавьте входные данные к содержимому поля редактирования.

I created 2 sample MFC MDI projects (e.g. MDI_sample1 & MDI_Sample2). Keeping the default cpp & h files as is, just added a new class (e.g. CwEdit) that subclasses the CEdit class to both MDI_Sample1 & MDI_Sample2 projects. Now, in MDI_Sample1, I open the *View.cpp, and add a WindowProc override. In this function, I check for the WM_KEYDOWN message, and on WM_KEYDOWN excepting VK_BACK, VK_ENTER, VK_TAB, I dynamically create an edit box using the CwEdit class, and then SendMessage a WM_KEYDOWN with the current wParam and lParam that I got as arguments of the WindowProc function. Running the program, I create a document and then press the key 'k'. An edit box will get created in the document. If IME is not being used, the character 'k' will also get entered into this newly created edit box. Next,I press 'a'and the character 'a' is appended to 'k' in the edit box. So far so good.

Затем я снова создаю новый документ. На этот раз я активирую windows IME на японский язык и ввожу "k". Опять же, будет создано окно редактирования, и оно будет отображать букву "К" с волнистыми подчеркиваниями. Я ввожу "а", и он правильно отображает японский иероглиф "я". Опять же, ожидаемо и правильно.

I copy this exe file to a windows 10 1709 machine and run it. Again, I repeat the same steps above to input the character 'k'. Without IME being active, the box is created and the 'k' is entered into it. Next I press 'a' and the edit box will correctly read 'ka'. Next, I create a new document. This time, I activate the windows IME to japanese and input 'k'. Again, an edit box will get created but it will be empty. I input 'a' and it now displays the japanese character 'あ'. This behaviour happens to all characters. The first keydown which was used to create the edit box will not be shown when IME is active. But once the edit box is created, everything works fine.

Я копирую весь код в MDI_Sample2. Но есть одно маленькое изменение. На этот раз в представлении я переопределяю PreTranslateMessage и выполняю точно такой же процесс, который ранее выполнялся внутри WindowProc. И удалите переопределение WindowProc. Этот MDI_Sample2 отлично работает как на Windows 7, так и на Windows 10 1709, даже когда японский IME активен.

Что я уже пробовал:

Код для *View.cpp для обоих проектов они приведены ниже:

MDI_Sample1View.cpp
*******************

BOOL MDI_Sample1View::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
    {
	    // TODO: Add your specialized code here and/or call the base class
	    if(message == WM_CHAR)
	    {
		    int wp = static_cast<int>(wParam);
		    // All printable ascii characters
		    if (wp >= 0x32 && wp <= 0x255)
		    {
			    EnableEdit();
			    M_pEdit->SendMessage(message, wParam, lParam);
			    return TRUE;
		    }
	    }
	    else if(message == WM_KEYDOWN)
	    {
		    if (wParam == VK_ESCAPE)
		    {
			    if(M_pEdit &&
				    GetFocus() == M_pEdit)
			    {
				    DisableEdit();
				    return TRUE;
    			}
	    	}
		    EnableEdit();
    	}
	    return CView::WindowProc(message, wParam, lParam);
    }
MDI_Sample2View.cpp
*******************
BOOL MDI_Sample2View::PreTranslateMessage(MSG* pMsg)
    {
	    // TODO: Add your specialized code here and/or call the base class
	    if(pMsg->message == WM_CHAR)
	    {
		    int wp = static_cast<int>(pMsg->wParam);
		    // All printable ascii characters
		    if (wp >= 0x32 && wp <= 0x255)
		    {
			    EnableEdit();
			    M_pEdit->SendMessage(pMsg->message, pMsg->wParam, pMsg->lParam);
			    return TRUE;
		    }
	    }
	    else if(pMsg->message == WM_KEYDOWN)
	    {
		    if (pMsg->wParam == VK_ESCAPE)
		    {
			    if(M_pEdit &&
				    GetFocus() == M_pEdit)
			    {
				    DisableEdit();
				    return TRUE;
    			}
	    	}
		    EnableEdit();
    	}
	    return CView::PreTranslateMessage(pMsg);
    }
Все остальные файлы такие же, как и созданные visual studio при создании нового проекта.
Тот самый CwEdit.cpp класс имеет 2 функции, а именно Create для создания поля редактирования и OnKeyDown, который приведен ниже:
void CwSpEdit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
    {
	    if(nChar == VK_ESCAPE)
    	{
	    	SetWindowText(_T(""));
		    return;
    	}
	    CEdit::OnKeyDown(nChar, nRepCnt, nFlags);
    }
В остальном оба проекта идентичны. Итак, что же здесь происходит? Почему WindowProc игнорирует первый символ, в то время как PreTranslateMessage работает нормально?

Как мне решить эту проблему? Мне нужно заставить его работать с WindowProc, как это было раньше.

1 Ответов

Рейтинг:
0

KarstenK

Звучит немного похоже на настройки локали или языка. Это также может произойти при компиляции с различными строковыми флагами. Например, для многобайтовых или unicode.

Поэтому проверьте настройки проекта и IME для этих проблем и скомпилируйте оба проекта в UNICODE. Microsoft имеет традицию изменять поведение в своих различных версиях Windows, в основном в виде исправлений ошибок или новых стандартов.

Имейте в виду, что символы или японские знаки имеют более высокие значения, чем 255, поэтому усечение в символе или проверка ниже 255 являются ошибки.


princektd

@KarstenK проблема, похоже, заключается в некотором обновлении под капотом того, как работает IME... Все работает так, как и должно быть с Windows 7 ~ Windows 10 вплоть до обновления Creators Update. Эта проблема возникает после обновления до Windows 10 build 1709...

Проект уже настроен для Unicode, и проблема возникает только при первом нажатии клавиши на IME. после этого он работает нормально.
That is, if I use IME to type 'sakura', an edit box is created on the 's' KeyDown event. After creating the edit box, the 's' is entered into it, followed by the rest of the characters so that you finally get 'sakura' which IME converts to the japanese input 'さくら' in the IME composition window, and pressing the Enter key will confirm this word into the created edit box. This is the expected behaviour and works correctly prior to Windows 10 Creators Update. But after updating to the Creator's Update, the same input works differently in that, on the 's' KeyDown, the edit box is created, but after that, for some reason, it does not get included into the IME composition. So, typing 'sakura' as before now inputs 'akura'which IME converts to the japanese input 'あくら'.
The conversion to japanese in itself is correct. In the first case the japanese character is 'さ' which corresponds to 'sa', while in the 2nd case, the first japanese character is 'あ' which correctly corresponds to 'a'. As you can see, the first character 's' is missing. This problem can be seen as you are typing, that is, normally, as soon as you type 's', IME composition window will display it as an 's' with wavy underlines. The next keystroke 'a' will be appended to the existing 's' and will get converted to 'さ'. You dont need to type the whole 'sakura' word to see the issue, as in Windows 10 1709, as you type 's', the edit box will be created, but the IME composition window will not be displayed with the 's' character. The next keystroke 'a' will now open the IME composition window and input 'a' into it, which will be converted to 'あ'. Thus, the first 's' keystroke seems to get discarded somewhere, though debugging generates no errors or warnings.

princektd

Кроме того, как показано в примере кода, эта проблема возникает, когда я пытаюсь обработать создание поля редактирования в переопределении 'WindowProc', в то время как,если я делаю создание поля редактирования в 'PreTranslateMessage', оно также отлично работает в Win 10 1709. Таким образом, возникает вопрос о том, что изменилось в работе WindowProc в Windows 10 1709 и как его обойти...