c00*_*0fd 6 c++ com winapi reverse-engineering richedit
该RichEdit控件有这个很烦人的功能。每次用户尝试将光标移过其“ 端点 ”时都会发出蜂鸣声。例如,您可以使用WordPad还实现RICHEDIT的进行测试。打开它,输入一些文本,然后Home按键。如果光标不在行首:
打Home键将它移到那里,但随后击中Home一次键会产生蜂鸣声。
乍一看,它似乎是覆盖WM_KEYDOWN和提示WM_KEYUP消息,并阻止RICHEDIT发出哔哔声的情况是一种解决方案...直到我真正开始执行它。但是不幸的是,它并没有听起来那么简单,因为该控件在许多情况下都发出哔哔声!因此,我的击键阻止代码实际上膨胀到了300多个行,而且我仍然看到有些按键不是我要考虑的,或者更糟的是,我可能会覆盖一些有用的行为。(有关详细信息,请阅读下面的内容。)
然后,我决定查看RICHEDIT控件本身的实现。确实可以肯定,例如,如果我们看一下Home按键的实现,C:\WINDOWS\SysWOW64\msftedit.dll我的Windows 10操作系统在映射的偏移量处具有?Home@CTxtSelection@@QAEHHH@Z(称为(或去public: int __thiscall CTxtSelection::Home(int,int)碎片化的))函数,该函数0x3FC00被硬编码为调用MessageBeep(MB_OK),或正是我要消除的内容:
而且,如果您查看0x6B64FD38上面的屏幕快照中的地址,则有一种内置的方法可以绕过它,看起来像是flag 0x800。
因此,深入研究msftedit.dll一下,似乎有一个称为?OnAllowBeep@CTxtEdit@@QAEJH@Z(或去public: long __thiscall CTxtEdit::OnAllowBeep(int)缠结)的函数可以修改以下标志:
经过更多研究后,我发现RICHEDIT控件内置了COM接口,例如ITextServices和ITextHost引用该标志TXTBIT_ALLOWBEEP的ITextServices::OnTxPropertyBitsChange方法。
但是不幸的是,我似乎找不到直接更改该TXTBIT_ALLOWBEEP标志的方式(COM不是我的强项。)我尝试着研究实现ITextHost,但是它有很多虚拟方法与我所用的无关。我试图实现我不知道如何实现。
有谁知道如何清除该TXTBIT_ALLOWBEEP标志?
PS。这就是为什么我没有采用覆盖按键的方法的原因:仅举一个例子。说,如果我覆盖VK_HOME按键。我需要确保光标不在该行的开头,而且也没有选择。但是,我需要确保Ctrl在光标位于窗口最上方的情况下该键没有按下。然后与Shift密钥相同,我什至Alt不知道该怎么做...等等。哦,这只是Home关键。还有上,下,左,右,PageUp,PageDown,End,Delete和Backspace。(这就是我所知道的。可能还有更多,而且我什至没有在谈论IME或其他键盘布局等。)换句话说,这变得一团糟!所以, 要走的路。
首先,我们需要向EM_GETOLEINTERFACE富编辑窗口发送消息-这是检索IRichEditOle对象,客户端可以使用该对象来访问富编辑控件的组件对象模型(COM)功能。
然后要获取ITextServices指针,请调用QueryInterface所IUnknown返回的私有指针EM_GETOLEINTERFACE。
这里存在有趣的一点- IID_ITextServices不太知名,但需要从Msftedit.dll进入运行时
Msftedit.dll导出名为IID_ITextServices的接口标识符(IID),可用于查询ITextServices接口的IUnknown指针。
在获得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();
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
116 次 |
| 最近记录: |