对系统菜单进行子类划分

Subclassing the System Menu

本文关键字:子类 划分 系统 菜单      更新时间:2023-10-16

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

目前,我已经使用了以下两个代码片段来尝试对其进行子类化(在覆盖CFrameWnd::LoadFrame中):

  1. 尝试1:mSysMenuCMenu的子类,它也覆盖了Attach以自动将菜单设置为所有者绘制(bool参数只是用来通知它是否是系统菜单)

    mSysMenu.Attach(GetSystemMenu(FALSE)->GetSafeHmenu(), true);
    

    当我右键单击任务栏按钮,在wincore.cpp(在CWnd::OnMeasureItem中)中生成3个断言,并生成一个丑陋的、变形的所有者绘制的菜单时,这个操作失败了——这与_AFX_THREAD_STATE类有关。然而,当我在右键单击任务栏之前从OnLButtonDown调用它的TrackPopupMenu时,一切都很好。

  2. 尝试2:这个只是创建了一个类似变形的菜单测量,但没有任何所有者绘制尝试的迹象

    CVSPMenu* sysMenu = (CVSPMenu*)CMenu::FromHandle(GetSystemMenu(FALSE)->GetSafeHmenu());
    sysMenu->SetOwnderDrawn(true);
    

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

所以我的问题是,如何以及在哪里对系统菜单进行子类化?

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

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

我上次提到治疗中有一个优化的系统菜单,显著减少了系统。

当窗口具有WS_SYSMENU窗口样式时,但直到有人在那个窗口上调用Get­System­Menu,才有人知道它的菜单句柄是什么。在此之前,窗口管理器不会实际上必须致力于为窗口创建菜单;它可以假装窗户上有一个。(这个技巧很奇特name惰性初始化。)

窗口管理器创建一个全局默认系统菜单,其中包含标准系统菜单项。如果有人按下Alt+Space或否则会调用一个从未有过的窗口的系统菜单调用Get­System­Menu,窗口管理器只使用全局默认系统菜单,因为它知道没有人自定义菜单(你不能自定义你没有句柄的菜单!)大多数人从不自定义他们的系统菜单,这种优化避免将桌面堆中的相同副本弄得一团糟菜单这在16位天,所有窗口管理器对象都必须放入一个64KB堆(称为系统资源)。

如果你真的很狡猾,你可以瞥见难以捉摸的东西全局默认系统菜单:与任何其他弹出窗口一样菜单,显示的菜单的句柄将传递给窗口的WM_INIT­MENU­POPUP,如果您的程序从未调用Get­System­Menu,您将看到的句柄是全局默认值系统菜单。请注意,你不能对这个菜单做太多,因为窗口管理器阻止任何修改它的尝试。(否则,您的程序的菜单修改会对其他程序的菜单!)

因此,如果您的程序习惯于修改其系统菜单的WM_INIT­menu­POPUP处理程序中,您应该粘贴一个伪调用在WM_CREATE处理程序中获取系统菜单,以强制执行系统菜单从假装的系统菜单变为真实的系统菜单。