TrackPopupMenu 显示的系统菜单与窗口状态不匹配



在我的Qt应用程序上,我使用DwmExtendFrameIntoClientArea来扩展窗口内的Aero Glass,并且我已经处理了WM_NCCALCSIZE WinEvent以在非工作区绘制Qt小部件。

此外,在我的应用程序上,我已经处理了WM_NCRBUTTONUP WinEvent,以在窗口的工作区内显示窗口系统(标题栏)菜单。

菜单有效,我

的意思是,我可以通过该菜单恢复、最大化、最小化和关闭窗口,但是,有时菜单的启用项与窗口的状态不匹配,例如:有时该菜单不启用还原,但在已经最大化的窗口中启用最大化,而我对通过 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);
}

基于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);
}

显然,您需要手动设置启用和禁用的项目。

最新更新