C ++如何在将文本粘贴到编辑控件时替换新行?
C++ How to replace new lines when pasting a text to the Edit control?
我有一个简单的聊天程序。我对输入框使用 "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
只有第一行被粘贴到打字window:
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,但是当我尝试粘贴包含多行的文本时,根本没有粘贴任何文本,我只能听到 "beep" 声音.
我知道我可以通过检测剪贴板更改然后覆盖它来删除新行,但此解决方案会 "invade" 用户剪贴板,所以我不想使用它。
如有任何帮助,我将不胜感激。
感谢@RbMm 的帮助。我能够解决问题。
- 我没有使用编辑控件的子类,我试图处理父 window 中的 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);
然后是新的回调:
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;
}*/
}
我知道这不是一个完美的代码,但足以满足我的需要:)
我有一个简单的聊天程序。我对输入框使用 "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
只有第一行被粘贴到打字window:
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,但是当我尝试粘贴包含多行的文本时,根本没有粘贴任何文本,我只能听到 "beep" 声音.
我知道我可以通过检测剪贴板更改然后覆盖它来删除新行,但此解决方案会 "invade" 用户剪贴板,所以我不想使用它。
如有任何帮助,我将不胜感激。
感谢@RbMm 的帮助。我能够解决问题。
- 我没有使用编辑控件的子类,我试图处理父 window 中的 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);
然后是新的回调:
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;
}*/
}
我知道这不是一个完美的代码,但足以满足我的需要:)