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