我已经定义了一个所有者绘制的菜单类。该课程考虑了this article中定义的系统菜单的MeasureItem
问题(即根据菜单是否为系统菜单调整自定义测量)。但是我遇到的问题是在正确的时间对系统菜单进行子类化。
目前我已使用以下两个代码段尝试对其进行子类化(在覆盖CFrameWnd::LoadFrame
中):
尝试1:mSysMenu
是CMenu
的子类,它还重写Attach
以自动将菜单设置为所有者绘制(bool参数只是传递给notify是否是系统菜单)
mSysMenu.Attach(GetSystemMenu(FALSE)->GetSafeHmenu(), true);
当我右键单击任务栏按钮,在wincore.cpp
(在CWnd::OnMeasureItem
中)生成3个断言以及一个丑陋,变形的所有者绘制菜单时,这个失败了 - 与{{1}有关}类。
但是,当我从_AFX_THREAD_STATE
调用TrackPopupMenu
时,在我右键单击任务栏之前,eveything就可以了。
尝试2:这个只会创建一个类似变形的菜单测量,但没有任何所有者绘制尝试的迹象
OnLButtonDown
我也试过在CVSPMenu* sysMenu = (CVSPMenu*)CMenu::FromHandle(GetSystemMenu(FALSE)->GetSafeHmenu());
sysMenu->SetOwnderDrawn(true);
中做事,但是传入的菜单指针似乎并没有使用(只是导致断言和失败)。
所以我的问题是,我如何以及在哪里继承系统菜单?
答案 0 :(得分:0)
由于MSDN链接已失效,我已通过web.archive将其复活,并粘贴了以下相关文本。
我上次提到治疗方法有优化 系统菜单的数量,大大减少了 系统。
当窗口具有WS_SYSMENU窗口样式时,它具有系统菜单, 但是直到有人在该窗口上调用GetSystemMenu之前,没人知道 它的菜单句柄是什么。在那之前,窗口管理器不会 实际上必须致力于为窗口创建菜单;它可以 假装窗口有一个。 (这种技术很花哨 名称延迟初始化。)
窗口管理器创建一个全局默认系统菜单,其中包含 标准系统菜单项。如果有人按Alt + Space或 否则,调出系统菜单以获取从未有过的窗口 调用GetSystemMenu,窗口管理器只使用全局 默认系统菜单,因为它知道没有人自定义 菜单。 (您无法自定义没有句柄的菜单!) 大多数人从来没有自定义他们的系统菜单,这种优化 避免使用相同的相同副本使桌面堆变得混乱 菜单。早在 16位天,此时所有窗口管理器对象都必须放入一个 64KB堆(称为系统资源)。
如果您真的很偷偷摸摸,可以瞥见难以捉摸的 闪烁的全局默认系统菜单:与其他任何弹出窗口一样 菜单,将显示菜单的句柄传递给您 窗口的WM_INITMENUPOPUP,如果您的程序从未调用过 获取系统菜单,您将看到的句柄是全局默认值 系统菜单。请注意,您不能对此菜单执行太多操作,因为 窗口管理器阻止任何修改它的尝试。 (否则,您的 程序的菜单修改将对 其他程序的菜单!)
因此,如果您的程序习惯于修改其系统 在其WM_INITMENUPOPUP处理程序中的菜单上,您应该粘贴一个虚拟呼叫 WM_CREATE处理程序中的GetSystemMenu强制系统菜单 可以从假装系统菜单更改为真实菜单。