gpt4 book ai didi

c++ - 如何消除 RICHEDIT 控件的 MessageBeep?

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:23:09 26 4
gpt4 key购买 nike

RichEdit control有这个非常烦人的功能。每当用户试图将光标移过它的“终点”时,它就会发出哔哔声。例如,您可以使用 WordPad 对其进行测试这也实现了 RICHEDIT。打开它,输入一些文字,然后点击Home。 key 。如果光标不在行首:

enter image description here

点击 Home键将它移到那里,但随后点击 Home再次按键会发出此蜂鸣声。

乍一看好像是重写了WM_KEYDOWNWM_KEYUP消息并阻止 RICHEDIT 可以发出哔哔声的情况是一个解决方案……直到我真正开始实现它。不幸的是,它并不像听起来那么简单,因为在很多情况下该控件都会发出哔哔声!因此,我的击键阻止代码确实膨胀到 300 多行,而且我仍然看到有一些我没有考虑到的按键,或者更糟的是,我可能已经覆盖了一些有用的行为。 (阅读下文了解更多详情。)


然后我决定深入了解 RICHEDIT 控件本身的实现。果然,例如,如果我们看一下 Home 的实现按键,C:\WINDOWS\SysWOW64\msftedit.dll在我的 Windows 10 操作系统上,有一个名为 ?Home@CTxtSelection@@QAEHHH@Z 的函数(或 public: int __thiscall CTxtSelection::Home(int,int) demangled)在映射偏移 0x3FC00 ,即硬编码调用 MessageBeep (MB_OK),或者正是我要消除的东西:

enter image description here

如果您查看地址 0x6B64FD38在上面的屏幕截图中,有一种内置的方法可以绕过它,看起来是标志 0x800 .

所以深入研究了msftedit.dll再多一点,似乎有一个名为 ?OnAllowBeep@CTxtEdit@@QAEJH@Z 的函数(或 public: long __thiscall CTxtEdit::OnAllowBeep(int) demangled)可以修改此标志:

enter image description here

经过更多研究,我发现RICHEDIT 控件中内置了COM 接口(interface),例如ITextServices。和 ITextHost将该标志引用为 TXTBIT_ALLOWBEEP ITextServices::OnTxPropertyBitsChange 方法。

不幸的是,我似乎无法找到直接更改 TXTBIT_ALLOWBEEP 的方法标志(COM 不是我的强项。)我尝试研究实现 ITextHost , 但它有很多虚方法与我想要实现的目标无关,我不知道如何实现。

有没有人知道如何清除 TXTBIT_ALLOWBEEP旗帜?


附言。这就是为什么我没有走覆盖按键的路线:只是给你举个例子。说,如果我重写 VK_HOME按键。我需要确保光标不在行的开头,而且没有选择。然而,我需要确保 Ctrl当光标位于窗口的最顶部时,键没有按下。然后与Shift相同 key ,我什至不确定是什么 Alt用它做......等等。哦,这只是 Home key 。还有上、下、左、右、PageUp、PageDown、End、Delete、Backspace。 (这就是我所知道的。可能还有更多,而且我什至没有谈论 IME 或其他键盘布局等)换句话说,它变得一团糟!因此,最终我意识到预测击键不是要走的路。

最佳答案

首先我们需要发送EM_GETOLEINTERFACE发送到 rich edit 窗口的消息 - 这是检索 IRichEditOle 对象,客户端可以使用该对象访问 rich edit 控件的组件对象模型 (COM) 功能。

然后检索 ITextServices指针,在 EM_GETOLEINTERFACE 返回的私有(private) IUnknown 指针上调用 QueryInterface .

这里存在有趣的一点 - IID_ITextServices 不是众所周知但需要在运行时从 Msftedit.dll 获取

来自 About Windowless Rich Edit Controls

Msftedit.dll exports an interface identifier (IID) called IID_ITextServices that you can use to query the IUnknown pointer for the ITextServices interface.

在我们得到ITextServices之后指针 - 我们可以调用 OnTxPropertyBitsChange使用 TXTBIT_ALLOWBEEP 掩码

代码示例:

#include <textserv.h>

if (HMODULE hmodRichEdit = LoadLibrary(L"Msftedit.dll"))
{
// create richedit window
if (HWND hwndRich = CreateWindowExW(0, MSFTEDIT_CLASS, ...))
{
if (IID* pIID_ITS = (IID*) GetProcAddress(hmodRichEdit, "IID_ITextServices"))
{
IUnknown* pUnk;
if (SendMessageW(hwndRich, EM_GETOLEINTERFACE, 0, (LPARAM)&pUnk))
{
ITextServices* pTxtSrv;
HRESULT hr = pUnk->QueryInterface(*pIID_ITS, (void**)&pTxtSrv);
pUnk->Release();
if (0 <= hr)
{
pTxtSrv->OnTxPropertyBitsChange(TXTBIT_ALLOWBEEP, 0);
pTxtSrv->Release();
}
}
}
}
}

关于c++ - 如何消除 RICHEDIT 控件的 MessageBeep?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55884687/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com