对系统菜单进行子类划分
Subclassing the System Menu
我定义了一个所有者绘制的菜单类。该类考虑了本文中定义的系统菜单的MeasureItem
问题(即根据菜单是否为系统菜单来调整自定义测量)。然而,我遇到的问题是在正确的时间对系统菜单进行子类化。
目前,我已经使用了以下两个代码片段来尝试对其进行子类化(在覆盖CFrameWnd::LoadFrame
中):
-
尝试1:
mSysMenu
是CMenu
的子类,它也覆盖了Attach
以自动将菜单设置为所有者绘制(bool参数只是用来通知它是否是系统菜单)mSysMenu.Attach(GetSystemMenu(FALSE)->GetSafeHmenu(), true);
当我右键单击任务栏按钮,在
wincore.cpp
(在CWnd::OnMeasureItem
中)中生成3个断言,并生成一个丑陋的、变形的所有者绘制的菜单时,这个操作失败了——这与_AFX_THREAD_STATE
类有关。然而,当我在右键单击任务栏之前从OnLButtonDown
调用它的TrackPopupMenu
时,一切都很好。 -
尝试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窗口样式时,但直到有人在那个窗口上调用GetSystemMenu,才有人知道它的菜单句柄是什么。在此之前,窗口管理器不会实际上必须致力于为窗口创建菜单;它可以假装窗户上有一个。(这个技巧很奇特name惰性初始化。)
窗口管理器创建一个全局默认系统菜单,其中包含标准系统菜单项。如果有人按下Alt+Space或否则会调用一个从未有过的窗口的系统菜单调用GetSystemMenu,窗口管理器只使用全局默认系统菜单,因为它知道没有人自定义菜单(你不能自定义你没有句柄的菜单!)大多数人从不自定义他们的系统菜单,这种优化避免将桌面堆中的相同副本弄得一团糟菜单这在16位天,所有窗口管理器对象都必须放入一个64KB堆(称为系统资源)。
如果你真的很狡猾,你可以瞥见难以捉摸的东西全局默认系统菜单:与任何其他弹出窗口一样菜单,显示的菜单的句柄将传递给窗口的WM_INITMENUPOPUP,如果您的程序从未调用GetSystemMenu,您将看到的句柄是全局默认值系统菜单。请注意,你不能对这个菜单做太多,因为窗口管理器阻止任何修改它的尝试。(否则,您的程序的菜单修改会对其他程序的菜单!)
因此,如果您的程序习惯于修改其系统菜单的WM_INITmenuPOPUP处理程序中,您应该粘贴一个伪调用在WM_CREATE处理程序中获取系统菜单,以强制执行系统菜单从假装的系统菜单变为真实的系统菜单。
- 继承期间显示未知行为的子类
- 通过指向指针数组的指针访问子类的属性
- 从父类方法返回子类对象
- c++, 在子类中,如何在没有对象的情况下访问父类的方法?
- 将父类对象强制转换为子类的问题
- 避免在C++中重复子类定义
- 将QOpenGLWidget子类转换为使用Metal而不是OpenGL的子类是否可行?
- 如何初始化矢量的模板化子类
- C++ 继承:将子类传递给需要基类的函数并获取子类行为
- 有没有办法按值将纯抽象类的所有子类传递给 C++ 中的函数?
- 使用子类覆盖基类中定义的函数
- 子类地址等于虚拟基类地址?
- 将子类方法声明为基类的友元
- C++子类共享变量?
- 如何检查模板专用化是否是基本模板的子类?
- 仅让特定类'Fabric'构造类'Foo'及其所有子类的实例
- 使用模板参数重载C++方法:如何使其适用于模板的子类?
- 基类中的默认析构函数禁用子类中的移动构造函数(如果有成员)
- 对系统菜单进行子类划分
- 如何在C++中同时对几个类进行子类划分