C ++如何在将文本粘贴到Edit控件时替换新行?

时间:2017-12-29 12:16:27

标签: c++ winapi editcontrol

我有一个简单的聊天程序。我在打字框中使用“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,但是当我尝试粘贴包含多行的文本时,根本没有粘贴任何文本,我只能听到“哔”声。

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

我非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

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

  1. 我没有使用编辑控件的子类,我试图在父窗口中处理WM_PASTE消息。
  2. 固定代码:

    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;
        }*/
    }
    

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