Есть ли способ заставить окно консоли мигать на панели задач программно?

В основном я сделал консольное приложение, которое выполняет какую-то задачу, которая занимает несколько минут. Я бы хотел, чтобы он мигал на панели задач, чтобы сообщить мне, когда он закончит свою работу.


person Davy8    schedule 27.05.2010    source источник
comment
Вот решение, которое может помочь: stackoverflow.com/questions/73162/   -  person Zack    schedule 27.05.2010


Ответы (4)


Использование ответьте, что @Zack опубликовал и другой, чтобы найти дескриптор консольного приложения Я придумал это, и это прекрасно работает.

class Program
{
    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool FlashWindowEx(ref FLASHWINFO pwfi);

    [StructLayout(LayoutKind.Sequential)]
    public struct FLASHWINFO
    {
        public UInt32 cbSize;
        public IntPtr hwnd;
        public UInt32 dwFlags;
        public UInt32 uCount;
        public Int32 dwTimeout;
    }

    public const UInt32 FLASHW_ALL = 3;

    static void Main(string[] args)
    {
        Console.WriteLine("Flashing NOW");
        FlashWindow(Process.GetCurrentProcess().MainWindowHandle);
        Console.WriteLine("Press any key to continue");
        Console.ReadKey();
    }

    private static void FlashWindow(IntPtr hWnd)
    {
        FLASHWINFO fInfo = new FLASHWINFO();

        fInfo.cbSize = Convert.ToUInt32(Marshal.SizeOf(fInfo));
        fInfo.hwnd = hWnd;
        fInfo.dwFlags = FLASHW_ALL;
        fInfo.uCount = UInt32.MaxValue;
        fInfo.dwTimeout = 0;

        FlashWindowEx(ref fInfo);
    }
}
person Daniel DiPaolo    schedule 27.05.2010
comment
Похоже, есть 3 разных способа получить дескриптор окна, но мне больше нравится ваш, так как он не PInvoke, чтобы сделать это, приняв его. - person Davy8; 27.05.2010
comment
Ух ты. Я использовал метод P/Invoke, чтобы получить дескриптор окна окна консоли, лол. msdn.microsoft.com/en-us/library/ms683175 (VS.85).aspx - person Zack; 27.05.2010

Объединяя ответ на вопрос, указанный в комментарии @Zack, и получение hwnd окна консоли, используя это, я смог заставить его работать. Это класс, который я создал:

public static class FlashWindow
{
    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool FlashWindowEx(ref FLASHWINFO pwfi);
    [DllImport("kernel32.dll")]
    static extern IntPtr GetConsoleWindow();

    [StructLayout(LayoutKind.Sequential)]
    public struct FLASHWINFO
    {
        public UInt32 cbSize;
        public IntPtr hwnd;
        public UInt32 dwFlags;
        public UInt32 uCount;
        public UInt32 dwTimeout;
    }

    public const UInt32 FLASHW_ALL = 3;

    public static void Flash()
    {
        FLASHWINFO fInfo = new FLASHWINFO();

        fInfo.cbSize = Convert.ToUInt32(Marshal.SizeOf(fInfo));
        fInfo.hwnd = GetConsoleWindow();
        fInfo.dwFlags = FLASHW_ALL;
        fInfo.uCount = UInt32.MaxValue;
        fInfo.dwTimeout = 0;

        FlashWindowEx(ref fInfo);
    }
}

Он никогда не перестанет мигать, пока не будет закрыт, но это не было важно для моих целей.

person Davy8    schedule 27.05.2010
comment
Я не смог найти Process.GetCurrentProcess().MainWindowHandle , может быть, потому что я использую .NET Core, но это сработало нормально. - person Imapler; 18.05.2018
comment
GetConsoleWindow() кажется наиболее правильным способом получения окна консоли, поскольку Windows использует отдельный процесс для размещения окна консоли, а Process.GetCurrentProcess().MainWindowHandle не работает, поскольку окно не принадлежит процессу приложения. - person sich; 30.09.2018

Я читал, что невозможно получить дескриптор окна консоли напрямую означает, но на самом деле это кажется довольно простым в .NET. Итак, это почти то же самое, что этот вопрос:

class Program
{
    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool FlashWindowEx(ref FLASHWINFO pwfi);

    [StructLayout(LayoutKind.Sequential)]
    public struct FLASHWINFO
    {
        public UInt32 cbSize;
        public IntPtr hwnd;
        public UInt32 dwFlags;
        public UInt32 uCount;
        public UInt32 dwTimeout;
    }

    public const UInt32 FLASHW_STOP = 0;
    public const UInt32 FLASHW_CAPTION = 1;
    public const UInt32 FLASHW_TRAY = 2;
    public const UInt32 FLASHW_ALL = 3;
    public const UInt32 FLASHW_TIMER = 4;
    public const UInt32 FLASHW_TIMERNOFG = 12; 

    static void Main(string[] args)
    {
        // Give you a few seconds to alt-tab away :)
        Thread.Sleep(2000);

        // Flash on the task bar, until the window becomes the foreground window.
        // Constants for other behaviors are defined above.
        FLASHWINFO fInfo = new FLASHWINFO();
        fInfo.cbSize = Convert.ToUInt32(Marshal.SizeOf(fInfo));
        fInfo.hwnd = Process.GetCurrentProcess().MainWindowHandle;
        fInfo.dwFlags = FLASHW_TRAY | FLASHW_TIMERNOFG;
        fInfo.uCount = UInt32.MaxValue;
        fInfo.dwTimeout = 0;
        FlashWindowEx(ref fInfo);

        // Wait for input so the app doesn't finish right away.
        Console.ReadLine();
    }
}
person Thorarin    schedule 27.05.2010
comment
Эта часть была важна для меня: fInfo.dwFlags = FLASHW_TRAY | FLASHW_TIMERNOFG; Это заставит окно перестать мигать при получении фокуса. - person Cesar; 29.03.2018

Я изучил проблему @Davy8, из-за которой мигание не прекращается. Решение было довольно простым, просто передайте константу FLASHW_STOP. Чтобы показать это, я дополнительно расширил статический класс @Davy8, включив в него статическую функцию StopFlashing. Я также решил добавить комментарии на основе документации Microsoft, чтобы было легко понять, почему они применяются в C#.

    /// <summary>
    /// Class for flashing a console window
    /// <see cref="https://docs.microsoft.com/en-us/windows/desktop/api/winuser/ns-winuser-flashwinfo"/>
    /// </summary>
    public static class FlashWindow
    {
        /// <summary>
        /// Flashes the specified window. It does not change the active state of the window.
        /// </summary>
        /// <param name="pwfi">FLASHWINFO</param>
        /// <see cref="https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-flashwindowex"/>
        /// <returns>If the window caption was drawn as active before the call, the return value is nonzero. Otherwise, the return value is zero.</returns>
        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool FlashWindowEx(ref FLASHWINFO pwfi);

        /// <summary>
        /// Retrieves the window handle used by the console associated with the calling process.
        /// </summary>
        /// <see cref="https://docs.microsoft.com/en-us/windows/console/getconsolewindow"/>
        /// <returns>The return value is a handle to the window used by the console associated with the calling process or NULL if there is no such associated console.</returns>
        [DllImport("kernel32.dll")]
        static extern IntPtr GetConsoleWindow();

        /// <summary>
        /// Contains the flash status for a window and the number of times the system should flash the window.
        /// <see cref="https://docs.microsoft.com/en-us/windows/desktop/api/winuser/ns-winuser-flashwinfo"/>
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct FLASHWINFO
        {
            /// <summary>
            /// The size of the structure, in bytes
            /// </summary>
            public UInt32 cbSize;

            /// <summary>
            /// A handle to the window to be flashed. The window can be either opened or minimized.
            /// </summary>
            public IntPtr hwnd;

            /// <summary>
            /// The flash status. This parameter can be one or more of the following values.
            /// </summary>
            public UInt32 dwFlags;

            /// <summary>
            /// The number of times to flash the window.
            /// </summary>
            public UInt32 uCount;

            /// <summary>
            /// The rate at which the window is to be flashed, in milliseconds. If dwTimeout is zero, the function uses the default cursor blink rate.
            /// </summary>
            public UInt32 dwTimeout;
        }

        /// <summary>
        /// Flash both the window caption and taskbar button. This is equivalent to setting the FLASHW_CAPTION | FLASHW_TRAY flags.
        /// </summary>
        public const UInt32 FLASHW_ALL = 0x00000003;

        /// <summary>
        /// Flash the window caption.
        /// </summary>
        public const UInt32 FLASHW_CAPTION = 0x00000001;

        /// <summary>
        /// Stop flashing. The system restores the window to its original state.
        /// </summary>
        public const UInt32 FLASHW_STOP = 0x00000004;

        /// <summary>
        /// Flash continuously, until the FLASHW_STOP flag is set.
        /// </summary>
        public const UInt32 FLASHW_TIMER = 4;

        /// <summary>
        /// Flash continuously until the window comes to the foreground.
        /// </summary>
        public const UInt32 FLASHW_TIMERNOFG = 0x0000000C;

        /// <summary>
        /// Flash the taskbar button.
        /// </summary>
        public const UInt32 FLASHW_TRAY = 0x00000002;


        /// <summary>
        /// Create an instance of the FLASHWINFO structure
        /// </summary>
        /// <param name="flashwConstant">One of the provided FLASHW contant values</param>
        /// <param name="uCount">uCount to initialize the struct</param>
        /// <param name="dwTimeout">dwTimeout to initalize the struct</param>
        /// <returns>A fully instantiated FLASHWINFO struct</returns>
        private static FLASHWINFO GetFLASHWINFO(UInt32 flashwConstant, UInt32 uCount = UInt32.MaxValue, UInt32 dwTimeout = 0)
        {
            FLASHWINFO fInfo = new FLASHWINFO
            {
                hwnd = GetConsoleWindow(),
                dwFlags = flashwConstant,
                uCount = uCount,
                dwTimeout = dwTimeout
            };
            fInfo.cbSize = Convert.ToUInt32(Marshal.SizeOf(fInfo));
            return fInfo;
        }

        /// <summary>
        /// Flashes the console window (continues indefinitely)
        /// </summary>
        public static void Flash()
        {
            FLASHWINFO fInfo = GetFLASHWINFO(FLASHW_ALL);
            FlashWindowEx(ref fInfo);
        }

        /// <summary>
        /// Stops the flashing of the console window
        /// </summary>
        public static void StopFlash()
        {
            FLASHWINFO fInfo = GetFLASHWINFO(FLASHW_STOP);
            FlashWindowEx(ref fInfo);
        }
    }
person GLJ    schedule 20.05.2019