我考虑在Windows应用程序中使用所有者绘图菜单,该菜单应与标准菜单具有相同的外观。 (原因:标准菜单在某些混合DPI情况下无法正常工作。)
目前我在 WM_MEASUREITEM 期间提供正确宽度时遇到问题。
这是记事本编辑菜单的屏幕截图,其中每个项目都有一个快捷方式。
我们可以看到项目文本和快捷方式文本之间存在一个持续的差距,就好像它们是列一样。看起来好像项目文本的宽度和快捷方式文本的宽度是分开检索的,因为最长的项目文本“时间/日期”保留了适用于 Ctrl + A的快捷方式宽度虽然它只需要一个 F5 。
我找不到任何API功能,我可以单独给出项目文本的宽度和快捷方式文本,也没有找到任何指定差距大小的指标。
所以我的问题是:是否有可能在通常的 WM_MEASUREITEM 消息中实现所需的行为,如果是,如何?如果没有,是否有任何其他方法可以做到这一点,或者根本不可能?
答案 0 :(得分:0)
测量菜单项:
if ((p = wcschr( lpitem->Xlpstr, '\t' )) != NULL) {
RECT tmprc = rc;
LONG tmpheight;
int n = (int)( p - lpitem->Xlpstr);
/* Item contains a tab (only meaningful in popup menus) */
/* get text size before the tab */
txtheight = DrawTextW( hdc, lpitem->Xlpstr, n, &rc,
DT_SINGLELINE|DT_CALCRECT);
txtwidth = rc.right - rc.left;
p += 1; /* advance past the Tab */
/* get text size after the tab */
tmpheight = DrawTextW( hdc, p, -1, &tmprc,
DT_SINGLELINE|DT_CALCRECT);
lpitem->dxTab += txtwidth;
txtheight = max( txtheight, tmpheight);
txtwidth += MenuCharSize.cx + /* space for the tab */
tmprc.right - tmprc.left; /* space for the short cut */
}
然后绘制它:
Text = lpitem->Xlpstr;
if(Text)
{
for (i = 0; Text[i]; i++)
if (Text[i] == L'\t' || Text[i] == L'\b')
break;
}
if(lpitem->fState & MF_GRAYED)
DrawTextW( hdc, Text, i, &rect, uFormat);
/* paint the shortcut text */
if (!menuBar && L'\0' != Text[i]) /* There's a tab or flush-right char */
{
if (L'\t' == Text[i])
{
rect.left = lpitem->dxTab;
uFormat = DT_LEFT | DT_VCENTER | DT_SINGLELINE;
}
else
{
rect.right = lpitem->dxTab;
uFormat = DT_RIGHT | DT_VCENTER | DT_SINGLELINE;
}
DrawTextW( hdc, Text + i + 1, -1, &rect, uFormat );
}
因此,要在菜单项中插入键盘加速器,只需使用制表符将其与项目文本分开即可。然后,测量和绘图代码会查找此制表符并相应地执行操作。
但请注意,键盘加速器在菜单中右对齐,就像在屏幕截图中一样(使用DrawText
DT_RIGHT
实现),绘图代码需要它使用'\b'
字符与项目文本分隔,而不是制表符,除非我遗漏了某些内容,否则测量代码中不会考虑这些内容,因此您可能需要对此进行补偿。
答案 1 :(得分:0)
使用所有者绘制复制标准菜单是一个痛苦的世界。您必须打开和关闭视觉样式,助记符/ Access keys,辅助功能和所有未记录的指标。如果可以的话,最好只使用普通菜单。
每个Windows 10版本中的每个监视器DPI支持似乎都会发生变化。 1607添加了EnableNonClientDpiScaling
,它扩展了菜单和其他非客户区域。 1703添加了Per Monitor v2,MSDN说这是关于PMv2:
- 非客户区域的缩放 - 所有窗口将自动以DPI敏感方式绘制非客户区域。不需要调用EnableNonClientDpiScaling。
- 扩展Win32菜单 - 在Per Monitor v2上下文中创建的所有NTUSER菜单都将按监视器方式进行扩展。
记事本是PMv2,它的菜单似乎工作正常:
Windows 8.1和< 10周年更新需要更多的工作,我建议您不要在这些系统上声明自己DPI,并让Windows为您缩放窗口(有些模糊),如果系统有多个显示器。