RichEdit控件有一个非常让人讨厌的特性。每当用户试图将光标移动到其“结束点”之后时,它就会发出嗡嗡声。例如,您可以使用实现了RICHEDIT的WordPad
进行测试。打开它,输入一些文本,然后按下Home
键。如果光标不在行首:
Home
键将把光标移动到开头,但再次按下 Home
键会发出哔声。乍一看,似乎覆盖
WM_KEYDOWN
和 WM_KEYUP
消息并阻止 RICHEDIT 可能产生的哔声是一个解决方案... 直到我真正开始实现它。不幸的是,事情没有听起来那么简单,因为该控件在很多情况下都会发出哔声!因此,我的按键阻塞代码实际上膨胀到了300多行,而且我仍然看到有一些按键我没有考虑到,或者更糟糕的是,我可能已经覆盖了一些有用的行为。(请阅读下面的详细信息。)
然后我决定查看RICHEDIT控件本身的实现。如果我们看一下
Home
键按下的实现,例如在我的Windows 10操作系统上的C:\WINDOWS\SysWOW64\msftedit.dll
中,具有被称为?Home@CTxtSelection@@QAEHHH@Z
(或已解码的public:int __thiscall CTxtSelection :: Home(int,int)
)的函数,映射偏移量为0x3FC00
,硬编码为调用MessageBeep(MB_OK),或者正是我试图消除的内容。
如果你看一下上面截图中的地址0x6B64FD38
,会发现有一种内置方法可以绕过它,使用标志0x800
。
所以深入研究了一下msftedit.dll
后,似乎有一个名为?OnAllowBeep@CTxtEdit@@QAEJH@Z
(或者已解码的public: long __thiscall CTxtEdit::OnAllowBeep(int)
)的函数可以修改这些标志:
经过进一步的研究,我发现RICHEDIT控件内置了COM接口,例如ITextServices
和ITextHost
,这些接口在ITextServices::OnTxPropertyBitsChange
方法中引用了标志TXTBIT_ALLOWBEEP
。
不幸的是,我似乎找不到直接更改TXTBIT_ALLOWBEEP
标志的方法(COM不是我的专长)。我尝试着实现ITextHost
,但它有很多虚拟方法与我试图实现的内容无关,我不知道如何实现。
有没有人知道如何清除TXTBIT_ALLOWBEEP
标志?
< p > < em > PS. 这就是为什么我没有选择覆盖按键的路线:举个例子,如果我覆盖 < code > VK_HOME 键。我需要确保光标不在行首,但也没有选择。然而,在光标位于窗口顶部的情况下,我需要确保 < code > Ctrl 键没有按下。然后同样适用于 < code > Shift 键,而我甚至不确定 < code > Alt 与此有何关系......等等。哦,这只是 < code > Home 键。还有上下左右、PageUp、PageDown、End、Delete、Backspace。 (这就是我知道的。可能还有更多,而且我甚至没有谈论 IME 或其他键盘布局等问题。)换句话说,这变得一团糟! 所以,最终我意识到,预测按键不是正确的方法。
EM_GETOLEINTERFACE
发送到 richedit 窗口,然后查询ITextServices
接口并调用pTxtSrv->OnTxPropertyBitsChange(TXTBIT_ALLOWBEEP, 0);
。这一切都很简单,但在链接的问题下没有这样的答案。 - RbMm