Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Force window to blink when a particular event occurs in C# / WPF

Tags:

c#

.net

wpf

I am using C# / WPF to make an application. In that application, I want to blink the window if a particular event occurs so that user of that application knows that something happened. How can I get this in my C# WPF application.

Like in Yahoo Messenger, if you get a message then the message window blinks to get your focus, I want to use that effect in my application.

like image 252
Aqeel Avatar asked Jan 19 '12 10:01

Aqeel


3 Answers

Flashing the window and taskbar in a similar way to IM notifications can be accomplished in WPF using the following code. It uses PlatformInvoke to call the WinAPI function FlashWindowEx using the Win32 Handle of the WPF Application.Current.MainWindow

Code

public class FlashWindowHelper
{
    private IntPtr mainWindowHWnd;
    private Application theApp;

    public FlashWindowHelper(Application app)
    {
        this.theApp = app;
    }

    public void FlashApplicationWindow()
    {
        InitializeHandle();
        Flash(this.mainWindowHWnd, 5);
    }

    public void StopFlashing()
    {
        InitializeHandle();

        if (Win2000OrLater)
        {
            FLASHWINFO fi = CreateFlashInfoStruct(this.mainWindowHWnd, FLASHW_STOP, uint.MaxValue, 0);
            FlashWindowEx(ref fi);
        }
    }

    private void InitializeHandle()
    {
        if (this.mainWindowHWnd == IntPtr.Zero)
        {
            // Delayed creation of Main Window IntPtr as Application.Current passed in to ctor does not have the MainWindow set at that time
            var mainWindow = this.theApp.MainWindow;
            this.mainWindowHWnd = new System.Windows.Interop.WindowInteropHelper(mainWindow).Handle;
        }
    }

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

    [StructLayout(LayoutKind.Sequential)]
    private struct FLASHWINFO
    {
        /// <summary>
        /// The size of the structure in bytes.
        /// </summary>
        public uint 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.
        /// </summary>
        public uint dwFlags;
        /// <summary>
        /// The number of times to Flash the window.
        /// </summary>
        public uint uCount;
        /// <summary>
        /// The rate at which the Window is to be flashed, in milliseconds. If Zero, the function uses the default cursor blink rate.
        /// </summary>
        public uint dwTimeout;
    }

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

    /// <summary>
    /// Flash the window caption.
    /// </summary>
    public const uint FLASHW_CAPTION = 1;

    /// <summary>
    /// Flash the taskbar button.
    /// </summary>
    public const uint FLASHW_TRAY = 2;

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

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

    /// <summary>
    /// Flash continuously until the window comes to the foreground.
    /// </summary>
    public const uint FLASHW_TIMERNOFG = 12;

    /// <summary>
    /// Flash the spacified Window (Form) until it recieves focus.
    /// </summary>
    /// <param name="hwnd"></param>
    /// <returns></returns>
    public static bool Flash(IntPtr hwnd)
    {
        // Make sure we're running under Windows 2000 or later
        if (Win2000OrLater)
        {
            FLASHWINFO fi = CreateFlashInfoStruct(hwnd, FLASHW_ALL | FLASHW_TIMERNOFG, uint.MaxValue, 0);

            return FlashWindowEx(ref fi);
        }
        return false;
    }

    private static FLASHWINFO CreateFlashInfoStruct(IntPtr handle, uint flags, uint count, uint timeout)
    {
        FLASHWINFO fi = new FLASHWINFO();
        fi.cbSize = Convert.ToUInt32(Marshal.SizeOf(fi));
        fi.hwnd = handle;
        fi.dwFlags = flags;
        fi.uCount = count;
        fi.dwTimeout = timeout;
        return fi;
    }

    /// <summary>
    /// Flash the specified Window (form) for the specified number of times
    /// </summary>
    /// <param name="hwnd">The handle of the Window to Flash.</param>
    /// <param name="count">The number of times to Flash.</param>
    /// <returns></returns>
    public static bool Flash(IntPtr hwnd, uint count)
    {
        if (Win2000OrLater)
        {
            FLASHWINFO fi = CreateFlashInfoStruct(hwnd, FLASHW_ALL | FLASHW_TIMERNOFG, count, 0);

            return FlashWindowEx(ref fi);
        }            

        return false;
    }

    /// <summary>
    /// A boolean value indicating whether the application is running on Windows 2000 or later.
    /// </summary>
    private static bool Win2000OrLater
    {
        get { return Environment.OSVersion.Version.Major >= 5; }
    }
}

Usage

var helper = new FlashWindowHelper(Application.Current);

// Flashes the window and taskbar 5 times and stays solid 
// colored until user focuses the main window
helper.FlashApplicationWindow(); 

// Cancels the flash at any time
helper.StopFlashing();
like image 183
Dr. Andrew Burnett-Thompson Avatar answered Oct 01 '22 03:10

Dr. Andrew Burnett-Thompson


You could use TaskBarItem class to make the taskbar icon of your app blink.

Here is something that can help you achieve it.

Then you can flash, shake, fade-in fade-out, or whatever one of the other zillion FX using WPF Animations. It's very simple and requires almost no code at all, if you have Expression Blend the job is made even easier.

like image 27
Shimmy Weitzhandler Avatar answered Oct 01 '22 01:10

Shimmy Weitzhandler


Setting the ProgressState property to TaskbarItemProgressState.Indeterminate will blink the icon in green. You don have to use the progress bar.

http://msdn.microsoft.com/en-us/library/system.windows.shell.taskbaritemprogressstate.aspx

like image 31
tbt Avatar answered Oct 01 '22 02:10

tbt