- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我在 Windows 10 Creators 更新中遇到了一个问题,当我尝试使用 IME 向我的应用程序输入内容时,第一个字符被忽略;即,如果我使用 IME 通过输入 K & A 来输入日语平假名字符“か”,我最终只会得到“あ”,而 K 丢失了。这只发生在第一个字符上。但是完全相同的应用程序可以在 Windows 7~8 中正常运行。
详情如下:
该应用程序是容器/服务器类型的 MFC MDI 应用程序。它的工作非常简单直接。如果文档是打开的,那么当 WM_KEYDOWN 被触发时,动态创建一个 CEdit 框并将按下的键输入到编辑框中。如果编辑框已经存在,则无需重新创建。只需将输入附加到编辑框的内容中即可。
我创建了 2 个示例 MFC MDI 项目(例如 MDI_sample1 和 MDI_Sample2)。保持默认的 cpp & h 文件不变,只是添加了一个新类(例如 CwEdit),它将 CEdit 类子类化到 MDI_Sample1 和 MDI_Sample2 项目。现在,在 MDI_Sample1 中,我打开 *View.cpp,并添加一个 WindowProc 覆盖。在这个函数中,我检查 WM_KEYDOWN 消息,并在 WM_KEYDOWN 上,除了 VK_BACK、VK_ENTER、VK_TAB 之外,我使用 CwEdit 类动态创建一个编辑框,然后使用我作为参数的当前 wParam 和 lParam SendMessage 一个 WM_KEYDOWN WindowProc 函数。运行该程序,我创建一个文档,然后按“k”键。将在文档中创建一个编辑框。如果未使用 IME,字符 'k' 也将被输入到这个新创建的编辑框中。接下来,我按“a”,然后在编辑框中将字符“a”附加到“k”。到现在为止还挺好。
接下来,我再次创建一个新文档。这一次,我将 Windows IME 激活为日语并输入“k”。同样,将创建一个编辑框,它将显示带有波浪下划线的“k”。我输入'a',它正确显示了日语字符'か'。再次,预期和正确。
我将此exe文件复制到Windows 10 1709机器并运行它。同样,我重复上述相同的步骤来输入字符 'k'。在 IME 未激活的情况下,将创建该框并在其中输入“k”。接下来我按“a”,编辑框将正确读取“ka”。接下来,我创建一个新文档。这一次,我将 Windows IME 激活为日语并输入“k”。同样,将创建一个编辑框,但它将是空的。我输入'a',它现在显示日文字符'あ'。这种行为发生在所有角色身上。当 IME 处于事件状态时,用于创建编辑框的第一个 keydown 将不会显示。但是一旦创建了编辑框,一切正常。
我将整个代码复制到 MDI_Sample2。但是有一点点变化。这一次,在 View 中,我覆盖了 PreTranslateMessage 并执行了之前在 WindowProc 中完成的完全相同的过程。并删除 WindowProc 覆盖。即使日语 IME 处于事件状态,此 MDI_Sample2 在 Windows 7 和 Windows 10 1709 上也能完美运行。
两个项目的 *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);
}
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);
}
void CwSpEdit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if(nChar == VK_ESCAPE)
{
SetWindowText(_T(""));
return;
}
CEdit::OnKeyDown(nChar, nRepCnt, nFlags);
}
最佳答案
终于我想通了。
似乎 IME 行为在 Windows 10 1709 及更高版本中发生了变化。
我将用一个例子来解释不同的行为:
案例 1:Windows 10 1709 之前
-> 打开记事本。将 IME 设置为日语平假名,然后按“k”键。您将看到“带有波浪下划线的 k”。您需要一个或多个字符才能将这个“k”组合成一个适当的平假名。在您提供更多输入或按 Esc 取消输入之前,“k”将保留为未经确认的 IME 输入。保持原样,没有任何额外的输入,只需点击其他地方(如您的桌面),这样记事本就会失去焦点。您会注意到任务栏/语言栏中的 IME 指示器已更改。而且您可能还会看到 Windows 自己的 IME 组合窗口(Windows 7 中的黑色小窗口)弹出,其中包含您的“k”。现在回到记事本上,您会发现未经确认的“k”仍在等待您提供进一步的输入或取消它。简而言之,当焦点发生变化时,未确认的 IME 字符串仍然保持未确认状态。
案例 2:Windows 10 1709 以后:
-> 重复以上步骤。在这里你可以注意到不同之处。一旦焦点发生变化,IME 合成就会停止。因此,作为未确认的 IME 字符串的 'k' 将被丢弃。
在问题中给出的示例中,WindProc 和 PreTranslateMessage 发生的情况是,使用 WindProc,在 IME keyPress 上, View 处于焦点下并接收 KeyPress 消息。它处理它并将它传递给它的 child ,根据我们的代码,在那里创建一个新的编辑控件。现在,随着编辑控件的创建,它变得聚焦。并且根据新行为,当焦点从 View 更改为控件时,IME 组合将停止。由于这发生在第一次 IME 按键时,我们得到了一个仍处于未确认状态的字符。作为未经确认的 IME 字符,该字符被丢弃。
使用 PreTranslateMessage,我们接收按键消息并继续创建编辑控件。在创建时,编辑控件获得焦点而我们的 View 失去焦点。这将生成 KillFocus 消息,但由于我们仍处于前一个 KeyPress 消息处理的中间,因此没有处理 KillFocus 消息。它正在等待前面的消息处理完成。现在,当我们在创建控件后返回时,我们将按键传递给新创建的编辑框。因此,编辑框最终接收按键以及以下未经确认的 IME 字符。因此,根据我们的示例“k”按键,编辑框而不是 View 接收未经确认的“k”。下一个按键自然会被编辑框接收,因为它现在处于焦点下,因此第二个输入被添加到未确认的“k”中,并且像往常一样执行合成。
此行为不仅限于需要多次按键的字符。甚至像“a”这样的单个按键字符也有同样的作用,因为在我们按下 Enter 键或选择组合候选之一等之前,即使这些字符仍然未经确认。
关于c++ - Windows 10 1709 中日语输入法的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48093581/
我有这种来自 Google map 自动完成的奇怪行为(或者我可能错过了某事)...想法?奇怪的: 您在输入中输入某物,例如“伦敦” 您按 [ENTER] 你按下 [CLEAR] 按钮 你点击进入'输
这段代码与《Learning Java》(Oracle Press Books)一书中的代码完全一样,但它不起作用。我不明白为什么它不起作用,它应该起作用。我用 OpenJDK 和 Sun JDK 7
示例 1 中究竟发生了什么?这是如何解析的? # doesnt split on , [String]::Join(",",("aaaaa,aaaaa,aaaaa,aaaaa,aaaaa,aa
我需要获得方程式系统的解决方案。为此,我使用函数sgesv_()。 一切都很好,它使我感到解决方案的正确结果。 但是我得到一个奇怪的警告。 警告:从不兼容的指针类型传递'sgesv_'的参数3 我正在
我目前在制作动画时遇到一个奇怪的问题: [UIView animateWithDuration:3 delay:0
alert('works'); $(window).load(function () { alert('does not work'); });
我的代码: public class MyTest { public class StringSorter implements Comparator { public
我正在学习 JavaScript。尝试理解代码, function foo (){ var a = b = {name: 'Hai'}; document.write(a.name +''
这个问题不太可能帮助任何 future 的访问者;它只与一个小的地理区域、一个特定的时间点或一个非常狭窄的情况有关,这些情况并不普遍适用于互联网的全局受众。为了帮助使这个问题更广泛地适用,visit
这按预期工作: [dgorur@ted ~]$ env -i env [dgorur@ted ~]$ 这样做: [dgorur@ted ~]$ env -i which date which: no
struct BLA { int size_; int size()const{ return size_; } } int x; BLA b[ 2 ]; BLA * p = &b[
我有以下代码: #test img {vertical-align: middle;} div#test { border: 1px solid green; height: 150px; li
我想大多数使用过 C/C++ 的人都对预处理器的工作原理有一定的直觉(或多或少)。直到今天我也是这么认为的,但事实证明我的直觉是错误的。故事是这样的: 今天我尝试了一些东西,但我无法解释结果。首先考虑
我想为 TnSettings 做 mock,是的,如果通过以下方法编写代码,它就可以工作,问题是我们需要为每个案例编写 mock 代码,如果我们只 mock 一次然后执行多个案例,那么第二个将报告异常
我的项目中有以下两个结构 typedef volatile struct { unsigned char rx_buf[MAX_UART_BUF]; //Input buffer over U
Regex rx = new Regex(@"[+-]"); string[] substrings = rx.Split(expression); expression = "-9a3dcb
我的两个应用程序遇到了一个奇怪的问题。这是设置: 两个 tomcat/java 应用程序,在同一个网络中运行,连接到相同的 MS-SQL-Server。一个应用程序,恰好按顺序位于 DMZ 中可从互联
我目前正在与 Android Api Lvl 8 上的 OnLongClickListener 作斗争。 拿这段代码: this.webView.setOnLongClickListener(new
这个问题不太可能帮助任何 future 的访问者;它只与一个小的地理区域、一个特定的时间点或一个非常狭窄的情况相关,这些情况并不普遍适用于互联网的全局受众。为了帮助使这个问题更广泛地适用,visit
只是遇到了奇怪的事情。我有以下代码: -(void)ImageDownloadCompleat { [self performSelectorOnMainThread:@selector(up
我是一名优秀的程序员,十分优秀!