Owner-Drawn Menus绘制时如何区分子菜单项与菜单栏菜单项
自绘菜单区分顶层菜单栏项与子菜单项实现方案
可以明确区分两类菜单项,不同技术栈的实现方法如下:

1. Win32 API 实现
处理WM_DRAWITEM消息时,通过DRAWITEMSTRUCT结构体关联的菜单句柄判断父菜单是否存在即可:
- 顶层菜单栏菜单项的父菜单句柄为
NULL - 子菜单项的父菜单句柄为非
NULL值
示例代码:
LRESULT OnDrawItem(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam; if (lpdis->CtlType != ODT_MENU) return DefWindowProc(hWnd, uMsg, wParam, lParam); HMENU hCurrentMenu = lpdis->hwndItem; if (GetParent(hCurrentMenu) == NULL) { // 绘制顶层菜单栏项:按需求实现居中、自适应宽度等样式 } else { // 绘制子菜单项:设置文字左对齐、固定宽度 RECT drawRect = lpdis->rcItem; drawRect.right = drawRect.left + 200; // 固定宽度200px DrawText(lpdis->hDC, (LPCSTR)lpdis->itemData, -1, &drawRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE); } return TRUE; }
2. MFC 实现
重写CMenu类的DrawItem和MeasureItem方法,通过GetParent()返回值判断菜单项类型:
GetParent()返回nullptr为顶层菜单栏项GetParent()返回非nullptr为子菜单项,可在MeasureItem中直接指定固定宽度
示例代码:
void CCustomMenu::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct) { if (GetParent() != nullptr) { lpMeasureItemStruct->itemWidth = 200; // 子菜单项固定宽度 } else { // 顶层项根据文字内容计算宽度 CString text = GetMenuString(lpMeasureItemStruct->itemID); lpMeasureItemStruct->itemWidth = GetTextExtent(text).cx + 16; } lpMeasureItemStruct->itemHeight = 24; } void CCustomMenu::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { CString itemText = GetMenuString(lpDrawItemStruct->itemID); if (GetParent() == nullptr) { // 绘制顶层菜单栏项 DrawText(lpDrawItemStruct->hDC, itemText, &lpDrawItemStruct->rcItem, DT_CENTER | DT_VCENTER | DT_SINGLELINE); } else { // 绘制子菜单项 DrawText(lpDrawItemStruct->hDC, itemText, &lpDrawItemStruct->rcItem, DT_LEFT | DT_VCENTER | DT_SINGLELINE); } }
3. Qt 实现
可以通过两种方式实现:
- 代码层面判断:自定义
QMenu绘制逻辑时,若parentWidget()类型为QMenuBar则为顶层项,若为QMenu则为子项 - QSS样式直接区分:无需写逻辑代码,直接通过选择器设置不同样式
QSS示例:
/* 顶层菜单栏项样式 */ QMenuBar::item { padding: 4px 12px; text-align: center; } /* 子菜单项样式 */ QMenu::item { width: 200px; text-align: left; padding: 4px 8px; }
注意事项
- 子菜单项固定宽度需要大于所有子项文字+图标+快捷键的总宽度,避免内容被截断
- Win32/MFC环境下如果需要显示快捷键,记得在子项宽度中预留右侧快捷键的绘制区域
内容的提问来源于stack exchange,提问作者Gijahara
相关产品推荐
相关产品推荐

