如何在C ++中将自定义项目添加到系统菜单?

时间:2020-03-06 14:46:35  来源:igfitidea点击:

我需要枚举所有正在运行的应用程序。特别是所有顶部窗口。对于每个窗口,我需要将自定义项添加到该窗口的系统菜单。

我该如何在C ++中做到这一点?

更新。

我很高兴拥有适用于Windows,MacOS和Ubuntu的解决方案(尽管我不确定MacOS和Ubuntu是否具有"系统菜单"之类的东西)。

解决方案

一旦有了另一个窗口的顶级句柄,我们就可以调用GetMenu()来检索窗口的系统菜单,然后对其进行修改,例如:

HMENU hMenu = GetMenu(hwndNext);

我们可以使用EnumWindows()枚举顶级Windows。

对于我们问题的第二部分,我没有具体的答案,但是如果我们将窗口子类化,我想我们可以修改系统菜单。

编辑:或者做克里斯说:调用GetMenu()

回复:此更新请注意,即使Microsoft Windows也不要求Windows具有系统菜单。 GetMenu()可能返回0。我们还需要拦截窗口的创建,因为每个新的顶部窗口可能也需要它。

另外,我们提出的建议对其他应用程序具有侵入性。修改菜单时,如何确保它们不会损坏?以及如何确保抑制消息?特别是,我们如何确保在别人看到它们之前就将它们拦截?引用雷蒙德·陈(Raymond Chen)的话,想象如果两个程序尝试这样做会发生什么。

对于Windows,获取顶级窗口(除EnumWindows外,它使用回调)的另一种方法是获取桌面的第一个子对象,然后检索其所有同级对象:

HWND wnd = GetWindow(GetDesktopWindow(), GW_CHILD);
while (wnd) {
    // handle 'wnd' here
    // ...
    wnd = GetNextWindow(wnd, GW_HWNDNEXT);
}

至于获取系统菜单,请使用" GetSystemMenu"函数,将FALSE作为第二个参数。其他答案中提到的" GetMenu"将返回正常的窗口菜单。

但是请注意,虽然将自定义菜单项添加到外部进程的窗口很容易,但是响应该项目的选择有些棘手。我们将不得不向该过程中注入一些代码以便能够对窗口进行子类化,或者安装一个全局挂钩(可能是" WH_GETMESSAGE"或者" WH_CBT"类型)来监视" WM_SYSCOMMAND"消息。