编辑窗口自适应文本宽度调整:除MSFTEDIT_CLASS外的替代方案咨询
解决方案:无需
MSFTEDIT_CLASS调整单行编辑框宽度适配文本 当然有不少替代方案可以解决你的问题,不用非得依赖MSFTEDIT_CLASS和EN_REQUESTRESIZE。结合你遇到的「粘贴长文本被截断,EN_CHANGE只能拿到部分内容」的核心痛点,下面给你几个实用的思路:
方案1:先开启自动横向滚动避免文本截断
你的编辑框默认没有设置ES_AUTOHSCROLL样式,这会导致控件在文本超过显示宽度时直接截断内容,自然拿不到完整文本。先给控件加上这个样式,就能保留完整的粘贴内容,后续再动态调整窗口大小:
// 创建控件时添加ES_AUTOHSCROLL hwndEdit = CreateWindow(TEXT("EDIT"), TEXT("EDIT"), WS_BORDER | WS_CHILD | ES_LEFT | ES_AUTOHSCROLL, 100, 100, 100, 30, gHwnd, 0, hInst, 0);
之后在EN_CHANGE通知里,获取完整文本并计算所需宽度,再调整窗口:
case WM_COMMAND: if (HIWORD(wParam) == EN_CHANGE && LOWORD(wParam) == IDC_EDIT) { HWND hwndEdit = (HWND)lParam; // 获取文本长度 int textLen = GetWindowTextLength(hwndEdit); if (textLen == 0) break; TCHAR* text = malloc((textLen + 1) * sizeof(TCHAR)); GetWindowText(hwndEdit, text, textLen + 1); // 获取控件字体并计算文本宽度 HFONT hFont = (HFONT)SendMessage(hwndEdit, WM_GETFONT, 0, 0); HDC hdc = GetDC(hwndEdit); HFONT hOldFont = (HFONT)SelectObject(hdc, hFont); SIZE sz; GetTextExtentPoint32(hdc, text, textLen, &sz); SelectObject(hdc, hOldFont); ReleaseDC(hwndEdit, hdc); // 调整窗口宽度(加10像素边距避免紧贴边框) SetWindowPos(hwndEdit, NULL, 0, 0, sz.cx + 10, 30, SWP_NOMOVE | SWP_NOZORDER); free(text); } break;
方案2:拦截WM_PASTE消息提前处理
如果不想开启自动滚动,也可以直接拦截编辑框的WM_PASTE消息,先从剪贴板拿到完整文本,计算需要的宽度后调整窗口,再手动把文本粘贴进去:
// 假设你的编辑框有自定义窗口过程,或者在主窗口过程中判断消息目标 case WM_PASTE: if (hwnd == hwndEdit) { // 获取剪贴板文本 if (!OpenClipboard(hwnd)) break; HANDLE hClipData = GetClipboardData(CF_UNICODETEXT); if (!hClipData) { CloseClipboard(); break; } wchar_t* clipText = (wchar_t*)GlobalLock(hClipData); int textLen = wcslen(clipText); // 计算文本宽度(同方案1的字体+DC处理逻辑) HFONT hFont = (HFONT)SendMessage(hwndEdit, WM_GETFONT, 0, 0); HDC hdc = GetDC(hwndEdit); HFONT hOldFont = (HFONT)SelectObject(hdc, hFont); SIZE sz; GetTextExtentPoint32W(hdc, clipText, textLen, &sz); SelectObject(hdc, hOldFont); ReleaseDC(hwndEdit, hdc); // 先调整窗口大小 SetWindowPos(hwndEdit, NULL, 0, 0, sz.cx + 10, 30, SWP_NOMOVE | SWP_NOZORDER); // 粘贴完整文本 SetWindowTextW(hwndEdit, clipText); GlobalUnlock(hClipData); CloseClipboard(); return 0; // 拦截默认粘贴行为 } break;
方案3:用EM_GETTEXTEX强制获取完整文本
如果因为某些原因无法修改控件样式或拦截粘贴消息,还可以通过EM_GETTEXTEX消息直接从编辑控件中读取完整的原始文本(哪怕显示被截断),再计算宽度调整窗口:
TEXTEX textex = {0}; textex.cb = sizeof(TEXTEX); textex.flags = GT_DEFAULT; textex.codepage = CP_UNICODE; // 获取文本长度 int textLen = SendMessage(hwndEdit, EM_GETTEXTLENGTHEX, (WPARAM)&textex, 0); if (textLen > 0) { wchar_t* text = malloc((textLen + 1) * sizeof(wchar_t)); SendMessage(hwndEdit, EM_GETTEXTEX, (WPARAM)&textex, (LPARAM)text); // 后续计算宽度和调整窗口的逻辑同方案1 free(text); }
注意事项
- 计算文本宽度时一定要使用编辑控件的实际字体,否则结果会和显示效果不符;
- 调整窗口宽度时建议加少量边距(比如10像素),避免文本紧贴控件边框,提升视觉体验;
- 如果是多行编辑框,逻辑会略有不同,但你的场景是单行,以上方案完全适用。
内容的提问来源于stack exchange,提问作者Irbis
相关产品推荐
相关产品推荐

