Is there a way to make a console window flash in the task bar programmatically
I read that it wasn't possible to get the window handle of a console window through any direct means, but it seems to be pretty simple in .NET actually. So, it's pretty much the same as this question:
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();
}
}
Using the answer that @Zack posted and another one to find the handle of a console app I came up with this and it works great.
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);
}
}
Combining the answer in the question linked in @Zack's comment and getting the hwnd of a console window using this I was able to get it working. This is the class I created:
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);
}
}
It doesn't ever stop flashing until it's closed but that wasn't important for my purposes.
I looked into the issue @Davy8 had in which the flashing doesn't stop. The solution was pretty simple, just pass the FLASHW_STOP constant. To show this, I further augmented @Davy8's static class to include a StopFlashing static function. I also decided to add comments based on the Microsoft Documentation such that it is easy to see why these are applied in 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);
}
}