Win32 C++如何取消Edit编辑控件选中状态并使其失焦
Win32 C++ Edit控件取消选中、失焦实现方案
你遇到的点击控件外部仍能输入的问题,本质是Edit控件没有丢失键盘输入焦点,和文本选中状态是两个关联但独立的问题,不需要找特殊扩展样式,通过标准Win32 API即可实现。
核心实现逻辑
需要同时完成两个操作:
- 检测用户点击Edit控件外部区域的行为,主动转移输入焦点,阻断Edit接收键盘消息
- 清除Edit控件内的文本选中高亮,将光标移动到指定位置(通常是文本末尾)
具体代码实现
1. 修复原有代码的已知问题
你当前的代码存在两个明显错误,会导致功能异常:
WM_SETFONT消息发送目标错误,你发给了父窗口而非Edit控件本身,字体设置不会生效- 创建字体后立刻调用
DeleteObject删除字体资源,会导致控件渲染字体时出现异常,字体对象应该在窗口销毁阶段再释放
修正后的控件创建代码:
HFONT fontMain = CreateFont( -16, // 字体高度 0, // 字体宽度(0为自适应高度) 0, // 文本行倾斜角度 0, // 字体基线角度 FW_NORMAL, // 常规字重 FALSE, // 非斜体 FALSE, // 无下划线 FALSE, // 无删除线 ANSI_CHARSET, // 字符集 OUT_TT_PRECIS, // 输出精度 CLIP_DEFAULT_PRECIS, // 裁剪精度 ANTIALIASED_QUALITY, // 抗锯齿渲染 FF_DONTCARE|DEFAULT_PITCH, // 字体族与间距配置 TEXT("Calibri")); HWND editControl = CreateWindow( TEXT("EDIT"), TEXT("TEST TEXT"), WS_CHILD | WS_VISIBLE | ES_LEFT | ES_MULTILINE | WS_TABSTOP, x, y, width, height, window, (HMENU) 100, instance, NULL); // 给Edit控件设置字体,最后一个参数传TRUE让控件立即重绘 SendMessage(editControl, WM_SETFONT, (WPARAM)fontMain, TRUE); // 注意:fontMain 要在父窗口处理WM_DESTROY消息时再调用DeleteObject释放
2. 实现点击外部失焦+取消选中
在父窗口的窗口过程中处理WM_LBUTTONDOWN消息,判断点击位置不在Edit控件范围内时,执行焦点转移和取消选中操作:
case WM_LBUTTONDOWN: { POINT clickPt = { LOWORD(lParam), HIWORD(lParam) }; RECT editBounds; // 获取Edit控件相对于父窗口客户区的位置范围 GetWindowRect(editControl, &editBounds); ScreenToClient(hWnd, (LPPOINT)&editBounds.left); ScreenToClient(hWnd, (LPPOINT)&editBounds.right); if (!PtInRect(&editBounds, clickPt)) { // 点击位置在Edit外部:将焦点移回父窗口,Edit不再接收键盘输入 SetFocus(hWnd); // 取消文本选中:将选中起止位置都设为文本末尾,清除所有高亮 int textLen = GetWindowTextLength(editControl); SendMessage(editControl, EM_SETSEL, (WPARAM)textLen, (LPARAM)textLen); } return DefWindowProc(hWnd, uMsg, wParam, lParam); }
补充说明
- 如果需要在其他场景(比如按下回车确认输入、点击按钮提交内容)触发失焦,直接复用
SetFocus和EM_SETSEL两行代码即可 - 如果父窗口上还有其他子控件,给子控件加上
WS_TABSTOP样式后,点击其他子控件会自动抢夺输入焦点,不需要额外写处理逻辑 - 如果需要将光标移到文本开头而非末尾,只要把
EM_SETSEL的两个参数都设为0即可
内容的提问来源于stack exchange,提问作者Amrit Sanjeev
相关产品推荐
相关产品推荐

