C++ Win32开发:如何在子窗口中实时显示Direct2D矩形宽高数据

问题解答
1. 子窗口绘制文本是否只能使用DirectWrite?
不是。仅展示几行宽高数据的需求用GDI接口完全可以实现,操作比DirectWrite简单很多:
- 用
TextOut()/DrawText()就能直接绘制文本内容 - 截图里的虚线边框可以用
FrameRect()配合虚线画刷,或者DrawEdge()实现,几行代码即可完成 - 性能完全满足实时更新的需求,不需要引入更重的DirectWrite。
2. 子窗口类相关问题
你当前选用LISTBOX完全不符合需求,它自带列表项管理等大量冗余逻辑,没有必要使用:
- 如果你要子类化已有控件修改逻辑,可以调用
SetWindowLongPtrW(子窗口句柄, GWLP_WNDPROC, 自定义窗口过程地址)替换原有窗口过程,但是不推荐用LISTBOX做这件事 - 最优方案是自行注册一个轻量自定义窗口类,仅需要在程序初始化时注册一次,自定义窗口过程里只处理必要消息即可,没有多余逻辑,完全匹配你的需求。
自定义窗口类注册示例:
// 程序初始化时调用一次即可 WNDCLASSEX wc = {0}; wc.cbSize = sizeof(WNDCLASSEX); wc.lpfnWndProc = TextBoxWindowProc; // 自定义的子窗口过程 wc.hInstance = HINST_THISCOMPONENT; wc.lpszClassName = L"CustomTextBoxClass"; RegisterClassEx(&wc);
创建子窗口时把类名替换为L"CustomTextBoxClass"即可。
3. 子窗口拖动实现
不需要自己编写鼠标拖动逻辑,只需要在子窗口的窗口过程中处理WM_NCHITTEST消息,直接返回HTCAPTION即可,系统会默认把整个子窗口的客户区识别为标题栏,自动处理拖动移动逻辑。
4. 弹出对话框是否更合适?
不合适。弹出对话框默认携带标题栏、系统按钮等你不需要的控件元素,还要额外处理对话框消息逻辑,比自定义轻量子窗口更冗余。你当前的自定义子窗口方案已经足够轻量灵活,更适合仅展示浮动信息的场景。
附:子窗口过程最简实现示例
LRESULT CALLBACK TextBoxWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); RECT clientRect; GetClientRect(hwnd, &clientRect); // 绘制白色背景 FillRect(hdc, &clientRect, (HBRUSH)GetStockObject(WHITE_BRUSH)); // 绘制虚线边框 HPEN dashPen = CreatePen(PS_DASH, 1, RGB(0, 0, 0)); HGDIOBJ oldPen = SelectObject(hdc, dashPen); // 空画刷避免填充内部 HGDIOBJ oldBrush = SelectObject(hdc, GetStockObject(NULL_BRUSH)); Rectangle(hdc, clientRect.left, clientRect.top, clientRect.right, clientRect.bottom); // 恢复GDI对象 SelectObject(hdc, oldPen); SelectObject(hdc, oldBrush); DeleteObject(dashPen); // 绘制宽高文本,宽高数值可从绑定的DemoApp实例获取 DemoApp* pApp = (DemoApp*)GetWindowLongPtrW(hwnd, GWLP_USERDATA); WCHAR displayText[64]; swprintf(displayText, L"宽度:%d\n高度:%d", pApp->rectWidth, pApp->rectHeight); DrawTextW(hdc, displayText, -1, &clientRect, DT_LEFT | DT_TOP | DT_WORDBREAK); EndPaint(hwnd, &ps); return 0; } case WM_ERASEBKGND: // 直接返回TRUE避免重绘背景闪烁 return TRUE; case WM_NCHITTEST: // 全窗口可拖动 return HTCAPTION; default: return DefWindowProcW(hwnd, msg, wParam, lParam); } }
需要实时更新宽高时,只要调用InvalidateRect(子窗口句柄, NULL, FALSE)触发重绘即可。
内容的提问来源于stack exchange,提问作者Jraxon
相关产品推荐
相关产品推荐

