在WPF应用程序中,如何覆盖控制台关闭命令?

3

在我的WPF应用程序中,我将控制台窗口用作调试/消息窗口-我已经设置了选项以显示和隐藏窗口,所有这些都很好地工作。唯一的问题是,当用户关闭控制台窗口时,它会退出整个程序。我如何覆盖这个行为,使用户单击X按钮时只隐藏控制台窗口而不退出应用程序?

这是我目前所拥有的:

const int SW_HIDE = 0;
const int SW_SHOW = 5;
public static bool ConsoleVisible { get; private set; }

[DllImport("kernel32.dll")]
static extern IntPtr GetConsoleWindow();

[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);


public static void HideConsole()
{
    var handle = GetConsoleWindow();
    ShowWindow(handle, SW_HIDE);
    ConsoleVisible = false;

}
public static void ShowConsole()
{
    var handle = GetConsoleWindow();
    ShowWindow(handle, SW_SHOW);
    ConsoleVisible = true;
}

** 对于想要使用此代码的人,您需要:using System.Runtime.InteropServices;

该代码源自这个答案:https://dev59.com/53A65IYBdhLWcg3w5zDB#3571628

** 编辑 **

再看看,似乎不可能。我在这里看到一个答案:https://dev59.com/SGct5IYBdhLWcg3wnurg#12015131,它讨论了删除退出按钮的方法,这也是可以接受的,但它似乎是C++代码,我找不到它的C#替代品。

** 编辑 2 **

我能够找出转换为C#并将其编写为以下答案。


为什么不使用一个子窗口呢?无论如何,查看这个主题... https://groups.google.com/group/microsoft.public.dotnet.languages.csharp/tree/browse_frm/thread/c72efe6c358eca9e/588a7bf4cfb4832?pli=1 - tukaef
1
这种方法从一开始就似乎是错误的:如果您的应用程序是从命令提示符启动的,则您的应用程序不会获得新的控制台窗口,并且您的代码试图隐藏一个不属于您的窗口。 - user743382
谢谢 - 看起来我可能需要采用另一种方法。只是使用已经存在的窗口似乎很简单。 - Anthony Nichols
如果您使用Visual Studio,可以使用Debug.Write[Line],它将在Visual Studio调试窗口中弹出。不需要控制台。 - default
这个想法是,如果某些东西表现出奇怪的行为,或者最终用户想要查看幕后发生了什么,他们可以取消隐藏控制台窗口并查看已经发生的日志。弹出窗口是具有侵入性的。 - Anthony Nichols
2个回答

5

正如我们所讨论的那样,没有办法阻止控制台窗口关闭WPF/应用程序窗口。在Windows Vista之前,有一些解决方法,但自那时以来它们已被删除(可能是出于安全原因)。我能想到的解决方法是禁用控制台窗口上的退出按钮,并将显示/隐藏选项放置在我的应用程序中。应用程序启动类如下:

using System;
using System.Windows;
using System.Runtime.InteropServices;

namespace MyApp
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
        public App()
        {
            ConsoleVisible = true;
            DisableConsoleExit();
        }

        #region Console Window Commands

        // Show/Hide
        [DllImport("kernel32.dll")]
        static extern IntPtr GetConsoleWindow();
        [DllImport("user32.dll")]
        static extern bool ShowWindow(IntPtr hWnd, uint nCmdShow);

        const uint SW_HIDE = 0;
        const uint SW_SHOWNORMAL = 1;
        const uint SW_SHOWNOACTIVATE = 4; // Show without activating
        public static bool ConsoleVisible { get; private set; }

        public static void HideConsole()
        {
            IntPtr handle = GetConsoleWindow();
            ShowWindow(handle, SW_HIDE);
            ConsoleVisible = false;

        }
        public static void ShowConsole(bool active = true)
        {
            IntPtr handle = GetConsoleWindow();
            if (active) { ShowWindow(handle, SW_SHOWNORMAL); }
            else { ShowWindow(handle, SW_SHOWNOACTIVATE); }
            ConsoleVisible = true;
        }

        // Disable Console Exit Button
        [DllImport("user32.dll")]
        static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
        [DllImport("user32.dll")]
        static extern IntPtr DeleteMenu(IntPtr hMenu, uint uPosition, uint uFlags);

        const uint SC_CLOSE = 0xF060;
        const uint MF_BYCOMMAND = (uint)0x00000000L;

        public static void DisableConsoleExit()
        {
            IntPtr handle = GetConsoleWindow();
            IntPtr exitButton = GetSystemMenu(handle, false);
            if (exitButton != null) DeleteMenu(exitButton, SC_CLOSE, MF_BYCOMMAND);
        }

        #endregion
    }
}

希望这篇文章能帮到所有遇到类似问题的人。

0

我认为你应该考虑使用AllocConsole创建控制台,并使用FreeConsole释放它。这样,你就可以让用户关闭控制台窗口,同时保持WPF应用程序的运行。


1
我尝试使用AllocConsole创建控制台,如此处所示: http://msdn.microsoft.com/en-us/library/windows/desktop/ms682528(v=vs.85).aspx 但是当我关闭控制台窗口时,主应用程序仍然会关闭。 - Anthony Nichols
1
如果是这种情况,可能没有办法首先禁用此行为。您可以尝试解决方法,例如为控制台使用单独的进程,或禁用退出按钮并提供另一种可控方式来隐藏控制台窗口。 - Theodoros Chatzigiannakis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接