You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Win32 API:如何使用TextOut在工具栏空白区域绘制文本不被覆盖

工具栏子控件上方文本被遮挡的解决办法

问题原因

你当前的代码是在主窗口的WM_PAINT消息中绘制文本,而Windows系统的窗口绘制顺序是先绘制父窗口,再逐层绘制所有子窗口:主窗口绘制完成后,才会绘制工具栏、富文本框等一级子窗口,最后才会绘制工具栏内嵌的列表框、按钮等二级子窗口。你在主窗口绘制的文本处于最底层,会被后续绘制的子窗口内容完全覆盖,所以无法显示。

推荐解决方法

方案1:使用静态文本控件(最适合新手,无需处理绘制逻辑)

直接在工具栏上创建系统自带的静态文本控件展示标签,系统会自动处理层级和绘制,不会被其他控件覆盖。
在WM_CREATE创建完工具栏后,新增如下代码即可:

// 架构选择标签静态控件,坐标为相对于工具栏的客户区坐标
HWND hArchLabel = CreateWindow(WC_STATIC, ArchLabel, 
    WS_CHILD | WS_VISIBLE | SS_LEFT, 
    archListBoxPos + 20, 5, 100, 20, // 宽高可根据实际文本长度调整
    Toolbar, (HMENU)(ChildID1 + 5), GetModuleHandle(NULL), NULL);
// 编译按钮标签静态控件
HWND hBuildLabel = CreateWindow(WC_STATIC, BuildLabel, 
    WS_CHILD | WS_VISIBLE | SS_LEFT, 
    btListBoxPos, 5, 100, 20,
    Toolbar, (HMENU)(ChildID1 + 6), GetModuleHandle(NULL), NULL);

// 可选:将静态控件设为顶层,避免被后续创建的控件遮挡
SetWindowPos(hArchLabel, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
SetWindowPos(hBuildLabel, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);

创建完成后可以删除主窗口WM_PAINT中TextOut相关的绘制代码。

方案2:子类化工具栏自绘文本(适合需要自定义绘制效果的场景)

如果你需要自己用TextOut实现绘制,可以子类化工具栏窗口,在工具栏自身绘制完成后再绘制文本,保证文本层级高于工具栏背景,不会被工具栏自身的绘制覆盖。
实现步骤如下:

  1. 定义工具栏的子类化窗口过程和原窗口过程指针:
WNDPROC g_oldToolbarProc;
LRESULT CALLBACK ToolbarSubclassProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
        case WM_PAINT:
            // 先调用工具栏原有的窗口过程,完成工具栏背景、边框等基础绘制
            LRESULT ret = CallWindowProc(g_oldToolbarProc, hWnd, msg, wParam, lParam);
            // 自定义绘制文本
            HDC hdc = GetDC(hWnd);
            SetBkMode(hdc, TRANSPARENT); // 设置文本背景透明,和工具栏背景融合
            SetTextAlign(hdc, TA_TOP);
            // 注意:此处坐标为相对于工具栏左上角的客户区坐标,不要使用主窗口坐标
            TextOut(hdc, archListBoxPosInToolbar + 20, 5, ArchLabel, ARRAYSIZE(ArchLabel));
            TextOut(hdc, btListBoxPosInToolbar, 5, BuildLabel, ARRAYSIZE(BuildLabel));
            ReleaseDC(hWnd, hdc);
            return ret;
        default:
            return CallWindowProc(g_oldToolbarProc, hWnd, msg, wParam, lParam);
    }
}
  1. 在WM_CREATE中创建完工具栏后,绑定子类化过程:
g_oldToolbarProc = (WNDPROC)SetWindowLongPtr(Toolbar, GWLP_WNDPROC, (LONG_PTR)ToolbarSubclassProc);

如果不确定子控件在工具栏中的坐标,可以调用MapWindowPoints将主窗口坐标转换为工具栏相对坐标。


内容的提问来源于stack exchange,提问作者Dave B.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 05:48:02