【问题标题】:System menu shown by TrackPopupMenu does not matches the window stateTrackPopupMenu 显示的系统菜单与窗口状态不匹配
【发布时间】:2014-02-11 01:31:56
【问题描述】:

在我的 Qt 应用程序中,我使用 DwmExtendFrameIntoClientArea 在窗口内扩展 Aero Glass,并处理了 WM_NCCALCSIZE WinEvent 以在非客户区绘制 Qt 小部件。

另外,在我的应用程序中,我处理了WM_NCRBUTTONUP WinEvent 以在我的窗口客户区域内显示窗口系统(标题栏)菜单。

菜单有效,我的意思是,我可以通过该菜单恢复、最大化、最小化和关闭窗口,但是,有时菜单的启用项与窗口的状态不匹配,例如:有时该菜单不't 启用还原但启用已最大化的窗口上的最大化,而我对通过 Windows 任务栏显示的系统菜单没有问题

问题:如何正确显示与当前窗口状态匹配的菜单?

监听 WinEvents 的代码:

bool MainWindow::winEvent(MSG *msg, long *result)
{
    HWND hWnd = msg->hwnd;
    UINT message = msg->message;
    WPARAM wParam = msg->wParam;
    LPARAM lParam = msg->lParam;

    bool retval = false;
    LRESULT lRet = 0;

    switch(message)
    {
    case WM_NCHITTEST:
    {
        lRet = HitTestNCA(hWnd, lParam);
        DwmDefWindowProc(hWnd, message, wParam, lParam, &lRet);
        retval = true;
        break;
    }
    case WM_NCRBUTTONUP:
    {
        QPoint point = QCursor::pos();
        HMENU menu = GetSystemMenu(hWnd, FALSE);
        BOOL Selected = TrackPopupMenu(menu, TPM_RIGHTBUTTON | TPM_NONOTIFY | TPM_RETURNCMD, point.x(), point.y(), 0, hWnd, NULL);
        if(Selected) PostMessage(hWnd, WM_SYSCOMMAND, Selected, 0);
        break;
    }
    case WM_NCCALCSIZE:
    {
        retval = true;
        break;
    }
    default:
        break;
    }

    *result = lRet;

    if(retval) return true;

    return QMainWindow::winEvent(msg, result);
}

【问题讨论】:

    标签: c++ windows qt contextmenu


    【解决方案1】:

    基于 Firefox 源代码,我开发了以下代码来解决我的问题:

    HMENU hMenu = GetSystemMenu(hWnd, FALSE);
    
    if (hMenu)
    {
        MENUITEMINFO mii;
        mii.cbSize = sizeof(MENUITEMINFO);
        mii.fMask = MIIM_STATE;
        mii.fType = 0;
    
        // update the options
        mii.fState = MF_ENABLED;
        SetMenuItemInfo(hMenu, SC_RESTORE, FALSE, &mii);
        SetMenuItemInfo(hMenu, SC_SIZE, FALSE, &mii);
        SetMenuItemInfo(hMenu, SC_MOVE, FALSE, &mii);
        SetMenuItemInfo(hMenu, SC_MAXIMIZE, FALSE, &mii);
        SetMenuItemInfo(hMenu, SC_MINIMIZE, FALSE, &mii);
    
        mii.fState = MF_GRAYED;
    
        WINDOWPLACEMENT wp;
        GetWindowPlacement(hWnd, &wp);
    
        switch (wp.showCmd)
        {
        case SW_SHOWMAXIMIZED:
            SetMenuItemInfo(hMenu, SC_SIZE, FALSE, &mii);
            SetMenuItemInfo(hMenu, SC_MOVE, FALSE, &mii);
            SetMenuItemInfo(hMenu, SC_MAXIMIZE, FALSE, &mii);
            SetMenuDefaultItem(hMenu, SC_CLOSE, FALSE);
            break;
        case SW_SHOWMINIMIZED:
            SetMenuItemInfo(hMenu, SC_MINIMIZE, FALSE, &mii);
            SetMenuDefaultItem(hMenu, SC_RESTORE, FALSE);
            break;
        case SW_SHOWNORMAL:
            SetMenuItemInfo(hMenu, SC_RESTORE, FALSE, &mii);
            SetMenuDefaultItem(hMenu, SC_CLOSE, FALSE);
            break;
        }
    
        LPARAM cmd = TrackPopupMenu(hMenu, (TPM_RIGHTBUTTON | TPM_NONOTIFY | TPM_RETURNCMD),
                                    GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), NULL, hWnd, NULL);
    
        if (cmd) PostMessage(hWnd, WM_SYSCOMMAND, cmd, 0);
    }
    

    显然你需要手动设置启用和禁用项。

    【讨论】:

      猜你喜欢
      • 2011-03-05
      • 1970-01-01
      • 1970-01-01
      • 2011-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多