C++ Win32菜单栏绘制覆盖自绘菜单项问题如何解决
问题核心原因
你的代码存在3个直接导致该现象的错误,其中最核心的是错误释放了系统提供的绘制DC:
DrawMenuItem中手动调用ReleaseDC释放了系统传入的绘制上下文,导致后续菜单项绘制时DC失效,绘制操作直接被系统忽略,仅第一个菜单项能完成绘制,其余区域被菜单栏背景覆盖AppendMenu传参不符合自绘菜单的规则,导致自绘项绑定的自定义数据可能异常- GDI对象使用未遵循上下文恢复规范,可能导致DC状态污染
修复步骤
1. 移除错误的DC释放调用
直接删掉 DrawMenuItem 中最后一行 ReleaseDC(MainWindow, hDC);,DRAWITEMSTRUCT 传入的hDC由系统负责生命周期管理,禁止手动释放。
2. 修正自绘菜单的初始化参数
顶层自绘菜单项如果是弹出菜单入口,需要加上MF_POPUP标志,同时确保传入的字符串生命周期足够,不会被提前释放:
HMENU Bar = CreateMenu(); HMENU File = CreateMenu(); HMENU Edit = CreateMenu(); // 定义静态字符串保证生命周期与程序一致 static const WCHAR szFileMenu[] = L"File"; static const WCHAR szEditMenu[] = L"Edit"; AppendMenu(Bar, MF_OWNERDRAW | MF_POPUP, (UINT_PTR)File, (LPCWSTR)szFileMenu); AppendMenu(Bar, MF_OWNERDRAW | MF_POPUP, (UINT_PTR)Edit, (LPCWSTR)szEditMenu); MENUINFO Info; Info.cbSize = sizeof(Info); Info.fMask = MIM_BACKGROUND; Info.hbrBack = (HBRUSH)CreateSolidBrush(RGB(100, 100, 100)); SetMenuInfo(Bar, &Info); SetMenu(MainWindow, Bar);
3. 修正GDI对象使用规范
绘制完成后恢复DC的原有状态,避免GDI资源泄漏和状态污染:
VOID DrawMenuItem(LPDRAWITEMSTRUCT ItemStruct) { HDC hDC = ItemStruct->hDC; // 保存DC原有状态 HPEN hOldPen = (HPEN)SelectObject(hDC, GetStockObject(DC_PEN)); HBRUSH hOldBrush = (HBRUSH)SelectObject(hDC, GetStockObject(DC_BRUSH)); int oldBkMode = SetBkMode(hDC, TRANSPARENT); COLORREF oldTextColor = GetTextColor(hDC); if (ItemStruct->itemState & ODS_HOTLIGHT) { SetDCPenColor(hDC, RGB(20, 20, 20)); SetDCBrushColor(hDC, RGB(20, 20, 20)); SetTextColor(hDC, RGB(255, 255, 255)); } else { SetDCPenColor(hDC, RGB(70, 70, 70)); SetDCBrushColor(hDC, RGB(70, 70, 70)); SetTextColor(hDC, RGB(255, 255, 255)); } Rectangle(hDC, ItemStruct->rcItem.left, ItemStruct->rcItem.top, ItemStruct->rcItem.right, ItemStruct->rcItem.bottom); DrawText(hDC, (LPCWSTR)ItemStruct->itemData, -1, &ItemStruct->rcItem, DT_SINGLELINE | DT_CENTER | DT_VCENTER); // 恢复DC原有状态 SelectObject(hDC, hOldPen); SelectObject(hDC, hOldBrush); SetBkMode(hDC, oldBkMode); SetTextColor(hDC, oldTextColor); return; }
可选优化
可以将 MeasureMenuItem 中的 itemHeight 调整为20左右,避免文字因为高度不足被截断。
内容的提问来源于stack exchange,提问作者Gijahara
相关产品推荐
相关产品推荐

