子类化系统菜单

问题描述 投票:0回答:1

我已经定义了一个所有者绘制的菜单类。该类考虑了MeasureItem中定义的系统菜单的this article问题(即根据菜单是否为系统菜单调整自定义测量)。但是我遇到的问题是在正确的时间对系统菜单进行子类化。

目前我使用了以下两个代码片段来尝试将其子类化(在重写CFrameWnd::LoadFrame中):

  1. 尝试1:mSysMenuCMenu的子类,它还重写了Attach以自动将菜单设置为所有者绘制(bool参数只是传递以通知它是否是系统菜单) mSysMenu.Attach(GetSystemMenu(FALSE)->GetSafeHmenu(), true); 当我右键单击任务栏按钮,在wincore.cpp(在CWnd::OnMeasureItem中)生成3个断言和一个丑陋,变形的所有者绘制菜单时,这个失败了 - 与_AFX_THREAD_STATE类有关。然而,当我在TrackPopupMenu上调用OnLButtonDown之前,在我右键单击任务栏之前,eveything正常。
  2. 尝试2:这个只是创建一个类似变形的菜单测量,但没有任何所有者绘制尝试的迹象 CVSPMenu* sysMenu = (CVSPMenu*)CMenu::FromHandle(GetSystemMenu(FALSE)->GetSafeHmenu()); sysMenu->SetOwnderDrawn(true);

我也试过在OnInitMenuPopup做的事情,但传入的菜单指针似乎并没有使用(只是导致断言和失败)。

所以我的问题是,我如何以及在哪里继承系统菜单?

c++ windows winapi mfc menu
1个回答
0
投票

因为MSDN链接已经死了,我通过web.archive复活了它,并粘贴了下面的相关文本。

https://web.archive.org/web/20140413053140/http://blogs.msdn.com/b/oldnewthing/archive/2010/05/28/10016691.aspx

我上次提到系统菜单的处理有一个优化,这显着减少了系统中的菜单数量。

当一个窗口具有WS_SYSMENU窗口样式时,它有一个系统菜单,但是直到有人在该窗口上调用GetSystemMenu,没有人知道它的菜单句柄是什么。在此之前,窗口管理器实际上不必承诺为窗口创建菜单;它可以假装窗口有一个。 (这种技术通过花式名称延迟初始化。)

窗口管理器创建一个全局默认系统菜单,其中包含标准系统菜单项。如果有人按下Alt + Space或以其他方式调用系统菜单中没有调用GetSystemMenu的窗口,则窗口管理器只使用全局默认系统菜单,因为它知道没有人自定义菜单。 (您无法自定义没有句柄的菜单!)由于大多数人从不自定义系统菜单,因此这种优化可以避免使用相同菜单的相同副本来混乱桌面堆。这在16位时代是一个特别重要的优化,当时所有窗口管理器对象必须适合单个64KB堆(称为系统资源)。

如果你真的很狡猾,你可以瞥见难以捉摸的全局默认系统菜单,因为它会嗖嗖地说:与任何其他弹出菜单一样,显示的菜单句柄传递给你的窗口的WM_INITMENUPOPUP,如果你的程序从来没有称为GetSystemMenu,您将看到的句柄是全局默认系统菜单。请注意,由于窗口管理器会阻止任何修改它的尝试,因此您无法对此菜单执行任何操作。 (否则,程序的菜单修改会对其他程序的菜单产生意想不到的影响!)

因此,如果您的程序习惯在其WM_INITMENUPOPUP处理程序中修改其系统菜单,则应在WM_CREATE处理程序中对GetSystemMenu进行虚拟调用,以强制系统菜单从假装系统菜单更改为真实系统菜单。

© www.soinside.com 2019 - 2024. All rights reserved.