【问题标题】:C++ How to replace new lines when pasting a text to the Edit control?C ++如何在将文本粘贴到编辑控件时替换新行?
【发布时间】:2017-12-29 12:16:26
【问题描述】:

我有一个简单的聊天程序。我对输入框使用“CreateWindow”功能:

chat_handle_11 = CreateWindow("EDIT", "", WS_BORDER | WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | WS_EX_CONTROLPARENT, 226, 447, 424, 23, hWnd, NULL, NULL, NULL);
SendMessage(chat_handle_11, EM_LIMITTEXT, ChatTextLimitInBox, 0L);

当我粘贴任何包含换行符的文本时(使用鼠标右键单击或 ctrl+v),例如:

Test line 1 text
Test line 2 text
Test line 3 text

只有第一行被粘贴到输入窗口:

Test line 1 text

我想更改粘贴时的文本,以忽略换行符:

Test line 1 text Test line 2 text Test line 3 text

我尝试处理 WM_PASTE 消息,不幸的是它不起作用:

switch (message)
{
case WM_PASTE:
{
    MessageBox(NULL, "pasting", "pasting", MB_YESNO | MB_ICONQUESTION);
    break;
}
...

MessageBox 从未显示。在这种情况下,WM_PASTE 是正确的消息吗?

另外,我尝试将“ES_MULTILINE”添加到CreateWindow,但是当我尝试粘贴包含多行的文本时,根本没有粘贴任何文本,我只能听到“哔”的声音。

我知道我可以通过检测剪贴板更改来删除新行,然后覆盖它,但是这个解决方案会“侵入”用户剪贴板,所以我不想使用它。

我将非常感谢任何帮助。

【问题讨论】:

  • ES_MULTILINE 必须是如果你想要多行。 WS_EX_CONTROLPARENT 也必须是扩展样式,而不是样式
  • 是的,但是粘贴多行根本不起作用。我实际上想要在打字窗口中有一行。我现在能找到的最好的例子是谷歌浏览器地址栏。当我们将任何多行文本粘贴到其中时,它会被转换为单行并删除了换行符。
  • WM_PASTE - 你的子类编辑控件?
  • 是的,WM_PASTE 得到了完全编辑控件到您尝试粘贴文本的位置,但不是它的父项
  • 在什么问题上自己在WM_PASTE上获取剪贴板的上下文,自己处理文本(最简单的方法将'\r'和'\n'都替换为空格,但可以做任何事情。最后你自己发送EM_SETSEL + EM_REPLACESEL 并且不调用编辑原始处理程序

标签: c++ winapi editcontrol


【解决方案1】:

感谢@RbMm 的帮助。我能够解决这个问题。

  1. 我没有使用编辑控件的子类,而是尝试在父窗口中处理 WM_PASTE 消息。

固定代码:

chat_handle_11 = CreateWindow("EDIT", "", WS_BORDER | WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | WS_EX_CONTROLPARENT, 226, 447, 424, 23, hWnd, NULL, NULL, NULL);
SendMessage(chat_handle_11, EM_LIMITTEXT, ChatTextLimitInBox, 0L);
SetWindowSubclass(chat_handle_11, EditBoxForPasteFixes, 0, 0);

然后是新的 CALLBACK:

LRESULT CALLBACK EditBoxForPasteFixes(HWND handle, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR, DWORD_PTR) {
    switch (uMsg) {
    case WM_PASTE:
    {
        try {
            wstring ClipboardText = GetClipboardText();
            find_and_replace_ws(ClipboardText, L"\r\n", L" ");
            find_and_replace_ws(ClipboardText, L"\r", L" ");
            find_and_replace_ws(ClipboardText, L"\n", L" ");
            //We don't need to SETSEL, so we keep original position for pasting
            //SendMessage(handle, EM_SETSEL, WPARAM(0), LPARAM(-1));
            SendMessageW(handle, EM_REPLACESEL, WPARAM(TRUE), LPARAM(ClipboardText.c_str()));
        }
        catch (...) {
            return FALSE;
        }
        return TRUE;
        break;
    }

    /*case WM_LBUTTONDOWN:
        //std::wcout << handle << L" click\n"; //click event works
        break;*/
    case WM_NCDESTROY:
    {
        RemoveWindowSubclass(handle, EditBoxForPasteFixes, 0);
        // fall through
    }
    default:
    {
        return DefSubclassProc(handle, uMsg, wParam, lParam);
    }
    }
    return 0;
}

以及GetClipboardText函数:

std::wstring GetClipboardText()
{
    bool Failed = false;
    std::wstring ReturnText = L"";
    // Try opening the clipboard
    if (!OpenClipboard(nullptr)) {
        Failed = true;
    }
    // Get handle of clipboard object for ANSI text
    if (!Failed) {
        //HANDLE hData = GetClipboardData(CF_TEXT);
        HANDLE hData = GetClipboardData(CF_UNICODETEXT);
        if (hData == nullptr) {
            Failed = true;
        }

        // Lock the handle to get the actual text pointer
        if (!Failed) {
            wchar_t * pszText = static_cast<wchar_t*>(GlobalLock(hData));
            if (pszText == nullptr) {
                Failed = true;
            }
            if (!Failed) {
                std::wstring text(pszText);
                ReturnText = text;
            }
            // Release the lock
            GlobalUnlock(hData);
        }
        // Release the clipboard
        CloseClipboard();
    }
    return ReturnText;
}

对于 find_and_replace_ws 我使用了 boost 功能,但可以用其他任何东西代替:

void find_and_replace_ws(wstring& source, wstring const& find, wstring const& replace)
{
    boost::replace_all(source, find, replace);
    /*for (std::string::size_type i = 0; (i = source.find(find, i)) != std::string::npos;)
    {
    source.replace(i, find.length(), replace);
    i += replace.length() - find.length() + 1;
    }*/
}

我知道,这不是一个完美的代码,但足以满足我的需要 :)

【讨论】:

  • 您可以通过删除failed 变量来简化代码。而是直接在if 语句中使用函数结果,例如。 G。 if(OpenClipboard(nullptr)) { HANDLE hData = GetClipboardData(CF_UNICODETEXT); /* ... and so on ... */}
猜你喜欢
  • 1970-01-01
  • 2011-05-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-04
  • 1970-01-01
相关资源
最近更新 更多