我正在为主机应用程序编写一个插件,我的插件使用 Rich Edit 控件。我想在用户将文本从控件复制或剪切到剪贴板时进行拦截,并将文本的自定义格式版本添加到剪贴板,我的主机应用程序比标准 RTF 或纯文本格式更好地理解该文本。
在咨询了法学硕士之后,这段代码似乎可能有效,或者至少让我开始了:
static LRESULT CALLBACK richEditSubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
switch (uMsg)
{
case WM_COPY:
case WM_CUT:
{
// capture the custom format of the selection here.
LRESULT retval = DefSubclassProc(hWnd, uMsg, wParam, lParam);
// add the custom format of the selection to the clipboard here.
return retval;
}
}
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}
但是,由于某种原因,当我按下 ctrl-X 或 ctrl-C 时,我在
WM_COPY
/WM_CUT
块上的断点永远不会命中。 (这些是剪切或复制的主要方法,因为我的对话框没有菜单。)这是我的 Rich Edit 子类例程的摘录。它已正确连接并可用于其他消息。
还有人有其他想法吗?最坏的情况是,我可以拦截 ctrl-C 和 ctrl-X 键,但一定有比这更简单的方法。为了一笑,我将此代码添加到主窗口过程中,但这些代码也没有命中。
(正如评论者所言)Rich Edit 控件似乎不能保证在内部响应键盘事件
WM_CUT
时发送 WM_COPY
/WM_PASTE
/ctrl-X/C/V
。看起来最安全(也有效)的解决方案是拦截键盘事件并将相关窗口消息发送回控件。这样做的好处是
static LRESULT CALLBACK richEditSubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
switch (uMsg)
{
case WM_COPY:
case WM_CUT:
{
// capture the custom format of the selection here.
LRESULT retval = DefSubclassProc(hWnd, uMsg, wParam, lParam);
// add the custom format of the selection to the clipboard here.
return retval;
}
case WM_PASTE:
if (OpenClipboard(nullptr))
{
bool handled = false;
UINT myFormat = RegisterClipboardFormatW(MY_CUSTOM_FORMAT);
HANDLE hData = GetClipboardData(myFormat);
if (hData != NULL)
{
// insert custom format into control here
handled = true
}
CloseClipboard();
if (handled) return 0;
}
break;
case WM_KEYDOWN:
if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
{
switch (wParam)
{
case 'C':
SendMessage(hWnd, WM_COPY, 0, 0);
return 0;
case 'X':
SendMessage(hWnd, WM_CUT, 0, 0);
return 0;
case 'V':
SendMessage(hWnd, WM_PASTE, 0, 0);
return 0;
}
}
break;
}
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}