winapi - 防止上下文菜单关闭

Posted

技术标签:

【中文标题】winapi - 防止上下文菜单关闭【英文标题】:winapi - prevent a context menu from closing 【发布时间】:2020-04-12 15:44:49 【问题描述】:

我有一个上下文菜单应该保持打开的场景。我使用了 WH_MSGFILTER 挂钩来接收上下文菜单消息。当用户单击上下文菜单项时,会打开一个用于选择颜色的对话窗口:

case WM_LBUTTONUP:

    if (colorSelected)
       
        //pMSG->message = WM_NULL; doesn't prevent context menu from closing when a dialog box is opened below
        currentColor = chooseColor(selectedMenuItemPos); //call ChooseColor winapi 
    
    break;

Here 是一个示例,如何防止上下文菜单在用户单击上下文菜单项时关闭。正如您在上面的代码中看到的那样,我也尝试了该方法,但是在打开对话框时它不起作用。在这种情况下是否可以保持上下文菜单打开? Here 是一个类似的问题,但可以使用上述方法解决。我对其他解决方案不感兴趣,例如假菜单窗口。我只是好奇在 winapi 中是否在技术上可行。

【问题讨论】:

【参考方案1】:

WH_CBT钩子可以通过处理HCBT_DESTROYWND来防止菜单关闭。

注册钩子:SetWindowsHookEx(WH_CBT, CBTProc, NULL, GetCurrentThreadId());

挂钩程序:

HRESULT CALLBACK CBTProc(
    int nCode, WPARAM wParam, LPARAM lParam
)

    switch (nCode)
    
    case HCBT_DESTROYWND:
    
        if((HWND)wParam == gMenuWindowHandle)
        
            return 1; // Return 1 to prevents closing window.
        
    
    break;
    

    return ::CallNextHookEx(NULL, nCode, wParam, lParam);

结果(About 是一个菜单项,About WindowsProject21 是一个对话框):

【讨论】:

我知道你已经发布了一个最小的例子,但是 HCBT_DESTROYWND 应该只为特定的窗口返回 1 - 在这种情况下是菜单的 HWND。有一个问题:当你关闭一个对话框窗口时,一个菜单被“冻结”了。 好的,但主要问题仍然存在 - 当您关闭对话框窗口时,菜单被“冻结”。 @Irbis 是的,还有其他问题,例如当您拖动主窗口时,“frozon”弹出窗口(菜单)将留在初始位置,而不是与主窗口一起移动,并且它的一部分。每次点击菜单时,都会显示一个窗口,用于监视鼠标事件并根据指定的事件采取行动,然后完成工作,销毁并消失,这是它的默认工作方式。当您更改其默认工作方式时,例如阻止其关闭,您有责任处理所有其余部分。可能不是一个问题就能解决的。 @Irbis 如果您想像往常一样保持菜单窗口打开和可点击,建议创建一个具有任何行为的类似菜单的窗口。请参阅 FakeMenu 示例。如果您想暂时保留窗口,请关闭它。下次您可以再次单击菜单,它将打开一个新窗口。如果这是您正在寻找的,是的,您可以记录打开的窗口并在以后销毁它以防止其他问题。但这仍然不是一个好习惯。

以上是关于winapi - 防止上下文菜单关闭的主要内容,如果未能解决你的问题,请参考以下文章

防止在 kineticJS 阶段右键单击默认上下文菜单?

WPF Datagrid行上下文菜单-禁用菜单项[关闭]

如何关闭material UI上下文菜单,而不显示默认的上下文菜单?

阻止ToolStripMenuItem上下文菜单关闭

如何以编程方式关闭 UIWebView 的上下文菜单?

如何将 Windows 终端添加到 Windows 10 上的上下文菜单? [关闭]