Win32 Edit控件按Enter提交消息时如何去除自动生成的CRLF换行
问题原因
你在子类化过程中捕获WM_KEYDOWN的Enter键、执行完提交清空逻辑后,没有拦截该消息,原生Edit控件的默认窗口过程仍会收到Enter键通知,自动执行插入换行符的默认逻辑,导致清空操作后控件被插入空行,光标停留在第二行。
原代码还有3个易引发异常的问题:
(LPCWSTR)""是错误写法:ANSI编码的空字符串强转为宽字符指针会读取到乱码,无法正确清空内容,清空控件应传入宽字符空串L""- 子类化过程中直接使用全局变量
hEdit不可靠:回调参数hWnd就是当前Edit控件的句柄,应直接使用该参数,避免多实例下句柄指向错误 - 所有非
default分支直接返回FALSE不符合Win32消息处理规范:未自定义处理的消息必须传递给原窗口过程,拿原过程的返回值作为回调返回值,否则会引发控件行为异常。
修复代码
核心修改点:处理完无Ctrl修饰的Enter键提交逻辑后,直接返回0终止消息传递,阻断Edit控件插入换行的默认行为;修正上述提到的隐性bug。
LRESULT CALLBACK SubEditProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ HDC hdc; RECT rt = { 20,20,200,500 }; switch (uMsg) { case WM_KEYDOWN: { switch (wParam) { case VK_RETURN: // 校验Ctrl键是否按下,0x8000为GetAsyncKeyState返回值中代表按键处于按下状态的标志位 if (!(GetAsyncKeyState(VK_CONTROL) & 0x8000)) { HWND hParent = GetParent(hWnd); hdc = GetDC(hParent); TCHAR buff[1024] = {0}; GetWindowText(hWnd, buff, 1024); // 直接用控件句柄清空内容,传入正确的宽字符空串 SetWindowText(hWnd, L""); DrawText(hdc, buff, -1, &rt, DT_LEFT); ReleaseDC(hParent, hdc); // 关键:已处理该消息,直接返回,不再传递给默认窗口过程 return 0; } // Ctrl+Enter组合键走默认逻辑,插入换行 break; } } break; default: break; } // 所有未自定义处理的消息,全部交给原Edit窗口过程处理,返回其执行结果 return CallWindowProc(DefEditProc, hWnd, uMsg, wParam, lParam); }
额外注意
要实现Ctrl+Enter换行,创建Edit控件时必须指定ES_MULTILINE样式,建议同时加上ES_WANTRETURN样式,让多行Edit原生识别回车输入,子类化逻辑仅拦截不带Ctrl的Enter键即可。
内容的提问来源于stack exchange,提问作者mille
相关产品推荐
相关产品推荐

