【问题标题】:Is there a way to disable right click menu in cmd? [closed]有没有办法在cmd中禁用右键菜单? [关闭]
【发布时间】:2019-09-24 11:48:25
【问题描述】:

我正在向控制台游戏引擎编写鼠标输入,但每次按下鼠标右键都会弹出上下文菜单并弄乱我的事件。

我的程序中的输入由附加到控制台的子窗口处理:

bool _CreateControl(HWND parent)
{
    WNDCLASSEX wx = {0};
    wx.cbSize = sizeof(WNDCLASSEX);
    wx.lpfnWndProc = HandleMessageSetup;        // function which will handle messages
    wx.hInstance = _GetInstance(self);
    wx.lpszClassName = this->wndClassName;

    if (RegisterClassEx(&wx)) 
    {
        this->Window = CreateWindowExW(0,
            this->wndClassName,
            L"dummy_name",
            WS_CHILD, 0, 0, 0, 0,     // make it a child
            parent,                   // parent here is console window
            NULL, _GetInstance(this), this);
        
        SetFocus(this->Window);       // give it a focus

        return true;
    }
    return false;
}

注意:此窗口的实例正在另一个线程中创建。

虽然我将焦点放在此窗口上以接收输入,但鼠标右键仍会为控制台生成事件并生成上下文菜单。

现在我正在处理 RAWMOUSEINPUT 并将 WM_INPUT 消息发送到我的窗口。这样做是因为我需要在 DirectInput 中稍微接近 GetMouseRelative() 来制作旋转相机。

控制台窗口用作图形输出。

有没有办法禁用父窗口输入处理?或者什么会导致这种行为,因为来自鼠标的输入正在由两个窗口处理?

【问题讨论】:

  • @pmg 我真的不知道如何做到这一点,因为我正在处理子窗口中的事件,接收焦点。因为我不能直接从控制台捕获任何东西,因为它在一个单独的进程中
  • 这与CMD无关。 CMD 是一个控制台程序,类似于您的用于操作计算机的控制台程序。 SetConsoleMode ENABLE_MOUSE_INPUT - 如果鼠标指针位于控制台窗口的边界内并且窗口具有键盘焦点,则由鼠标移动和按钮按下产生的鼠标事件将放置在输入缓冲区中。即使启用此模式,这些事件也会被 ReadFile 或 ReadConsole 丢弃。
  • @CodyGray 不,没错,RawInput 是必需的,因为我使用类似射击游戏的相机,如果我使用 WM_MOUSEMOVE,那么如果我的光标到达边界,它将停止。但我可以使用 ReadConsoleInput 的一部分来忽略 WM_CONTEXTMENU
  • 此评论线程正在讨论on Meta

标签: c windows winapi console


【解决方案1】:

您必须挂钩 SetFocus 函数,或者以其他方式指定 WM_KILLFOCUS 不应应用于您正在使用的命令提示符窗口。

SetFocus 函数向失去键盘焦点的窗口发送 WM_KILLFOCUS 消息,向接收键盘焦点的窗口发送 WM_SETFOCUS 消息。它还激活接收焦点的窗口或接收焦点的窗口的父窗口。

如果窗口处于活动状态但没有焦点,则按下任何键都会产生 WM_SYSCHAR、WM_SYSKEYDOWN 或 WM_SYSKEYUP 消息。如果同时按下 VK_MENU 键,则消息的 lParam 参数将设置第 30 位。否则,产生的消息没有设置该位。 通过使用 AttachThreadInput 函数,线程可以将其输入处理附加到另一个线程。这允许线程调用 SetFocus 将键盘焦点设置到附加到另一个线程的消息队列的窗口。

Excerpt from SetFocus at docs.microsoft.com

【讨论】:

  • 问题是:我不知道什么是 cmd 线程或我的,所以线程输入不起作用。我在 WM_KILLFOCUS 上做了一个SetFocus,但它只处理键盘消息,所以我需要以某种方式禁用鼠标消息在 CMD 中的工作
  • 即使超出了本题的范围,也可以使用WinAPI在processthreadsapi.h中提供的GetCurrentThreadId函数来获取当前线程ID。我不知道这是否对你正在做的事情有所帮助。
  • 挂钩函数不是实现特性的好方法。控制台窗口要么有这个功能,要么没有。
  • @immibis 我确实同意您关于挂钩函数“不是实现功能的好方法”的评论。然而,这并没有触及主题。
  • @CodyGray 如果传递了相关程序的句柄而不是下一个句柄,它应该根据 Microsoft 文档重定向到同一窗口。
【解决方案2】:

您可以通过自定义鼠标输入消息来禁用控制台的鼠标右键来达到这个目的。

需要注意的是,要添加ENABLE_EXTENDED_FLAGS(必须启用或禁用扩展标志)。

MSDN示例中没有添加这个,只有添加后才能处理鼠标消息。

fdwMode = ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT | ENABLE_EXTENDED_FLAGS;

另外,如果要禁用控制台的标题栏,可以参考以下代码。

HWND hwnd = GetConsoleWindow();
LONG Style = GetWindowLong(hwnd, GWL_STYLE);
SetWindowLong(hwnd, GWL_STYLE, Style &~ WS_CAPTION);

【讨论】:

    猜你喜欢
    • 2020-09-30
    • 2023-03-11
    • 2021-07-19
    • 1970-01-01
    • 2014-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-05
    相关资源
    最近更新 更多