将剪贴板类型添加到 Rich Edit 控件的复制类型

问题描述 投票:0回答:1

我正在为主机应用程序编写一个插件,我的插件使用 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 键,但一定有比这更简单的方法。为了一笑,我将此代码添加到主窗口过程中,但这些代码也没有命中。

winapi richedit
1个回答
0
投票

(正如评论者所言)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);
}
© www.soinside.com 2019 - 2024. All rights reserved.