子类化系统菜单

时间:2012-10-12 13:51:38

标签: c++ windows winapi mfc menu

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

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

  1. 尝试1:mSysMenuCMenu的子类,它还重写Attach以自动将菜单设置为所有者绘制(bool参数只是传递给notify是否是系统菜单)

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

    当我右键单击任务栏按钮,在wincore.cpp(在CWnd::OnMeasureItem中)生成3个断言以及一个丑陋,变形的所有者绘制菜单时,这个失败了 - 与{{1}有关}类。 但是,当我从_AFX_THREAD_STATE调用TrackPopupMenu时,在我右键单击任务栏之前,eveything就可以了。

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

    OnLButtonDown
  3. 我也试过在CVSPMenu* sysMenu = (CVSPMenu*)CMenu::FromHandle(GetSystemMenu(FALSE)->GetSafeHmenu()); sysMenu->SetOwnderDrawn(true); 中做事,但是传入的菜单指针似乎并没有使用(只是导致断言和失败)。

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

1 个答案:

答案 0 :(得分:0)

由于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之前,没人知道   它的菜单句柄是什么。在那之前,窗口管理器不会   实际上必须致力于为窗口创建菜单;它可以   假装窗口有一个。 (这种技术很花哨   名称延迟初始化。)

     

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

     

如果您真的很偷偷摸摸,可以瞥见难以捉摸的   闪烁的全局默认系统菜单:与其他任何弹出窗口一样   菜单,将显示菜单的句柄传递给您   窗口的WM_INIT­MENU­POPUP,如果您的程序从未调用过   获取­系统­菜单,您将看到的句柄是全局默认值   系统菜单。请注意,您不能对此菜单执行太多操作,因为   窗口管理器阻止任何修改它的尝试。 (否则,您的   程序的菜单修改将对   其他程序的菜单!)

     

因此,如果您的程序习惯于修改其系统   在其WM_INIT­MENU­POPUP处理程序中的菜单上,您应该粘贴一个虚拟呼叫   WM_CREATE处理程序中的Get­System­Menu强制系统菜单   可以从假装系统菜单更改为真实菜单。