【问题标题】:Getting a console window out of "select mode" to prevent a crash使控制台窗口脱离“选择模式”以防止崩溃
【发布时间】:2019-07-03 09:34:00
【问题描述】:

在我的 C# 应用程序中,我试图防止我的应用程序崩溃,基本上,我使用控制台窗口作为日志显示窗口。我已经通过禁用关闭窗口解决了“关闭按钮”问题,并使用 Show 和 Hide 调用显示/隐藏菜单,所有这些都工作得很好。

我的最后一个问题是文本选择是否处于活动状态并且窗口试图被隐藏。

我要么需要:

A.将窗口踢出选择模式。 (不知道我会怎么做,因为选择会暂停所有输出。)

B.以与禁用关闭菜单相同的方式禁用“编辑”菜单,希望它也会禁用鼠标选择,但我还没有找到任何方法来删除“编辑”菜单,我什至不确定这会阻止鼠标选择。

C.这似乎是最明显的,禁用鼠标选择,这是我目前在我的代码中的一个,但它不起作用,所以我不确定我错过了什么。

有问题的代码:

[DllImport("user32.dll")]
private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
 ....
[DllImport("Kernel32.dll", ExactSpelling = true)]
private static extern int SetConsoleMode(IntPtr hWnd, int wFlag);
 ....
public static void HideConsoleLog () {
    if (handle != IntPtr.Zero) {
        SetConsoleMode(handle, 0x0080);  // ENABLE_EXTENDED_FLAGS 0x0080
        ShowWindow(handle, (int)WinCntrlOpt.SW_HIDE);
        LogVisible = false;
    }
}

根据Documentation

ENABLE_EXTENDED_FLAGS 0x0080 需要启用或禁用扩展 标志。请参阅 ENABLE_INSERT_MODE 和 ENABLE_QUICK_EDIT_MODE。

还有……

ENABLE_QUICK_EDIT_MODE 0x0040 该标志使用户能够使用 鼠标选择和编辑文本。

要启用此模式,请使用 ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS。要禁用此模式,请使用 ENABLE_EXTENDED_FLAGS 没有这个标志。

所以,看来我这样做是正确的,它确实可以运行,但它不会阻止鼠标选择。不久前我确实知道这一点,Microsoft tinkered with Consoles,我不知道这是否破坏了这一点。

在堆栈交换上有一个similar question,但那下提供了一个可行的解决方案,实际上与我在 C 或 C++ 中尝试做的相反。我可以插值,但基本上我已经在这里尝试了。

这似乎是相同的建议,使用不带任何其他标志的 ENABLE_EXTENDED_FLAGS 来禁用该选项,这就是我所拥有的。但它不起作用。

所以,我要么在寻找错误的解决方案,要么没有正确地做其他事情。

效果是,当控制台窗口打开时,您可以使用鼠标选择文本,这会自动将控制台置于 Microsoft 修补添加的“选择模式”。这不是问题,但是当它处于该模式时,您选择“显示日志”(主应用程序窗口中的复选标记切换菜单选项)控制台窗口确实隐藏了,但随后主窗口锁定并应用程序崩溃。 (我的猜测是因为该窗口被该选择模式阻止。)当“选择模式”未激活时它不会崩溃。

我也想从同一个文档中尝试这个:

ENABLE_MOUSE_INPUT 0x0010 如果鼠标指针在边界内 控制台窗口和窗口具有键盘焦点、鼠标 鼠标移动和按钮按下产生的事件被放置在 输入缓冲区。这些事件被 ReadFile 或 ReadConsole,即使启用了此模式。

问题是,它说:

创建控制台时,除 ENABLE_WINDOW_INPUT 之外的所有输入模式 默认启用。

那么,我该如何禁用它呢?

我可以接受任何将其从选择模式中踢出或阻止它开始的解决方案,我在这里有我尝试过的东西。

【问题讨论】:

  • 与其禁用控制台功能,不如创建一个只包含所需功能的winform应用程序?

标签: c# windows console


【解决方案1】:

选择“Show Log”菜单选项时,窗口将最小化。 在窗口最小化之前,您必须检查用户是否选择了任何输入以防止崩溃。您可以使用GetConsoleSelectionInfo 检查用户是否选择了任何内容。

CONSOLE_SELECTION_INFOout 参数应该等于 0x00,如果不是,则需要处理选择。正如GetConsoleMode/SetConsoleMode 的文档所示,您需要调用ReadFileReadConsole 来丢弃可能正在进行的选择事件。

当你实现了这个之后,它应该不会再崩溃了。

【讨论】:

  • 这真的很有帮助!谢谢!我输入了 [DllImport("Kernel32.dll", ExactSpelling = true)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool GetConsoleSelectionInfo(out IntPtr lpConsoleSelectionInfo);并检查了 IntPtr.Zero 的结果指针,它按照您的描述工作。
猜你喜欢
  • 2017-02-26
  • 1970-01-01
  • 1970-01-01
  • 2019-03-09
  • 2018-01-15
  • 1970-01-01
  • 2012-10-14
  • 2012-06-06
  • 1970-01-01
相关资源
最近更新 更多