首页 > 解决方案 > Windows api编程-如何向应用程序窗口发送/发布消息以调用菜单项?

问题描述

问题

这周我一直在做一个 Windows 云桌面项目。一项功能要求服务器端可以响应来自客户端的用户输入(鼠标、键盘...)。我将来自客户端的输入消息(例如,WM_LBUTTONDOWN、WM_KEYDOWN...)发布到服务器中的特定应用程序窗口。当输入目标是应用程序窗口的客户区时,一切正常。但是,菜单栏的项目(例如 notepad.exe 中的“文件”)不响应鼠标单击事件。这里列出我的部分代码:

struct MouseMsg {
    UINT msg;
    WPARAM wParam;
    LPARAM lParam;
};

enum class MouseEvent : unsigned int {
    DOWN = 0,
    UP,
    MOVE,
    WHEEL
};

struct MouseInputData
{
    int32_t button;
    int32_t wheel;
    int32_t px;
    int32_t py;
};

void ConstructMouseClickMsg(MouseMsg& mouseMsg, MouseInputData* mData, MouseEvent motion) 
{
    mouseMsg.lParam = MAKELPARAM(mData->px, mData->py);
    switch (mData->button)
    {
        case 0:
        {
            mouseMsg.wParam = MK_LBUTTON;
            mouseMsg.msg = (motion == MouseEvent::DOWN) ? WM_LBUTTONDOWN : WM_LBUTTONUP;
            break;
        }
        case 1:
        {
            mouseMsg.wParam = MK_RBUTTON;
            mouseMsg.msg = (motion == MouseEvent::DOWN) ? WM_RBUTTONDOWN : WM_RBUTTONUP;
            break;
        }
        case 2:
        {
            mouseMsg.wParam = MK_MBUTTON;
            mouseMsg.msg = (motion == MouseEvent::DOWN) ? WM_MBUTTONDOWN : WM_MBUTTONUP;
            break;
        }
        default:
            LOG->warn("Unknown mouse button types");
            break;
    }
}

void OnMouseClick(MouseInputData* mData, MouseEvent motion)
{
    HWND mTargetHwnd = GetInputWindow();  // Omit details.
                                          // This function can get the target window's handle
                                          // and can tell if the window is client or menu (parent)
    if (!mTargetHwnd)
    {
        LOG->warn("Null window");
        return;
    }
    
    // construct mouse clicking messages
    MouseMsg mouseMsg;
    ConstructMouseClickMsg(mouseMsg, mData->button, motion);
    if (mIsClientArea)  // in client area or the menu bar? set in GetInputWindow()
    {
        PostMessageA(mTargetHwnd, mouseMsg.msg, mouseMsg.wParam, mouseMsg.lParam);
    }
    else
    {
        // How to ???
    }
}

我试过的

我使用 spy++ 来监视单击菜单栏时窗口收到的消息(如下图中的第 1296~1327 行所示)。WM_NCHITTEST、WM_NCLBUTTONDOWN、WM_SYSCOMMAND 似乎是解决方案。我尝试发布所有这些消息,但也没有回复。 在此处输入图像描述 试一试代码:

    if (mIsClientArea)  // in client area or the menu bar? set in GetInputWindow()
    {
        PostMessageA(mTargetHwnd, mouseMsg.msg, mouseMsg.wParam, mouseMsg.lParam);
    }
    else
    {
        // How to ???
        LOG->info("try to call up menu");
        if (motion == MouseEvent::DOWN)
        {
            PostMessageA(mTargetHwnd, WM_NCLBUTTONDOWN, HTMENU, mouseMsg.lParam);
            //PostMessageA(mCurrentHwnd, WM_SYSCOMMAND, SC_MOUSEMENU | 0x0005, mouseMsg.lParam);
        }
        else
        {
            PostMessageA(mTargetHwnd, WM_NCLBUTTONUP, HTMENU, mouseMsg.lParam);
        }
    }

帮助!!!

有没有Windows系统的专家可以给我一些提示?衷心感谢!

标签: c++windowswinapi

解决方案


推荐阅读