如何从RICHEDIT控件中消除MessageBeep?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何从RICHEDIT控件中消除MessageBeep?相关的知识,希望对你有一定的参考价值。
RichEdit control有这个非常讨厌的功能。每次用户尝试将光标移动到其“终点”时,它都会发出蜂鸣声。例如,您可以使用同样实现RICHEDIT的WordPad
对其进行测试。打开它,键入一些文本,然后点击Home
键。如果光标不在行的开头:
击中Home
键将移动它,但然后再次击中Home
键将产生这种哔哔声。
乍一看似乎压倒WM_KEYDOWN
和WM_KEYUP
消息并阻止情况,当RICHEDIT可以产生哔声是一个解决方案......直到我真正开始实施它。不幸的是,它并不像听起来那么简单,因为这种控制会在很多情况下发出哔哔声!所以我的击键阻止代码真的膨胀到超过300多行,我仍然看到有一些按键,我要么没有考虑,或者更糟糕的是,我可能已经覆盖了一些有用的行为。 (请阅读下面的详细信息。)
然后我决定查看RICHEDIT控件本身的实现。当然,例如,如果我们看看Home
按键的实现,我的Windows 10操作系统上的C:WINDOWSSysWOW64msftedit.dll
,在映射的偏移量?Home@CTxtSelection@@QAEHHH@Z
上有一个名为public: int __thiscall CTxtSelection::Home(int,int)
(或0x3FC00
demangled)的函数,它被硬编码为调用MessageBeep(MB_OK),或者正是我想要消除的:
如果你看一下上面屏幕截图中的地址0x6B64FD38
,就会有一种内置的方式来绕过它,看起来像是标志0x800
。
所以更多地挖掘msftedit.dll
,似乎有一个名为?OnAllowBeep@CTxtEdit@@QAEJH@Z
(或public: long __thiscall CTxtEdit::OnAllowBeep(int)
demangled)的函数可以修改这个标志:
经过一番研究后,我发现在RICHEDIT控件中内置了COM接口,例如ITextServices
和ITextHost
在TXTBIT_ALLOWBEEP
方法中将该标志引用为ITextServices::OnTxPropertyBitsChange
。
不幸的是,我似乎无法找到直接改变那个TXTBIT_ALLOWBEEP
旗帜的方式(COM不是我的强项。)我试图实现ITextHost
,但它有很多虚拟方法与什么无关我正在努力实现我不知道如何实现。
有谁知道如何清除TXTBIT_ALLOWBEEP
旗帜?
PS。这就是为什么我没有采用超越按键的原因:只是举个例子。说,如果我覆盖VK_HOME
键按。我需要确保光标不在行的开头,而且还没有选择。但是,当光标位于窗口的最顶端时,我需要确保Ctrl
键没有关闭。然后与Shift
键相同,我甚至不确定Alt
用它做什么......等等。哦,这只是Home
的关键。还有Up,Down,Left,Right,PageUp,PageDown,End,Delete,Backspace。 (这就是我所知道的。可能还有更多,而且我甚至不谈论IME或其他键盘布局等等)换句话说,它变得一团糟!所以,最终我意识到预期击键不是要走的路。
首先,我们需要将EM_GETOLEINTERFACE
消息发送到富编辑窗口 - 这是检索客户端可用于访问丰富的编辑控件的组件对象模型(COM)功能的IRichEditOle对象。
然后为了检索ITextServices
指针,在QueryInterface
返回的私有IUnknown
指针上调用EM_GETOLEINTERFACE
。
这里存在一些有趣的观点 - IID_ITextServices
并不为人所知,但需要从Msftedit.dll运行
来自About Windowless Rich Edit Controls
Msftedit.dll导出名为IID_ITextServices的接口标识符(IID),您可以使用该标识符查询ITextServices接口的IUnknown指针。
在我们得到qazxsw poi指针之后 - 我们根本无法用qazxsw poi面具调用qazxsw poi
代码示例:
ITextServices
以上是关于如何从RICHEDIT控件中消除MessageBeep?的主要内容,如果未能解决你的问题,请参考以下文章
如何正确处理来自 MSFTEDIT_CLASS (RichEdit) 控件的 Windows 消息?