В основном я сделал консольное приложение, которое выполняет некоторую задачу, которая занимает несколько минут. Я хотел бы, чтобы он запустился на панели задач, чтобы сообщить мне, когда это будет сделано.
Есть ли способ заставить окно консоли мигать программно на панели задач?
Ответ 1
Используя ответ, который @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);
}
}
Ответ 2
Я прочитал, что не удалось получить дескриптор окна окна консоли через какие-либо прямые средства, но, похоже, это довольно простой в .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();
}
}
Ответ 3
Объединяя ответ в вопросе, связанный с комментарием @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);
}
}
Он никогда не останавливается, пока он не закрывается, но это не важно для моих целей.
Ответ 4
Я посмотрел на проблему @Davy8, в которой мигание не прекращается. Решение было довольно простым, просто передайте константу FLASHW_STOP. Чтобы показать это, я добавил в статический класс @Davy8 функцию статической функции StopFlashing. Я также решил добавить комментарии на основе документации Microsoft, чтобы было легко понять, почему они применяются в С#.
/// <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);
}
}