归档/2025.02.27·windows技术/WPF

WPF上实现任务栏闪烁

想在 WPF 里实现类似微信来消息时任务栏闪烁的效果?这事还得靠调 Windows API 解决。我封装了一个好用的 C# 工具类,几行代码就能搞定任务栏的高亮提示。

最近做了客户端的IM联系窗口的功能,有一个需求是如果收到新的消息时,任务栏需要闪烁提醒用户。 效果类似于微信和飞书收到新消息。

Windows有提供任务栏闪烁的API,直接调API即可。我这里把相关的功能都封装了一下,作为一个工具类,分享出来。 知识点:

  1. 从C#侧调用win32的 api
  2. 把win32 api需要的参数用struct的的形式声明出来,并且标注StructLayout.Sequntial
public static class WpfHelper
{
    // 停止闪烁
    public const uint FLASHW_STOP = 0;
    // 闪烁窗口标题
    public const uint FLASHW_CAPTION = 1;
    // 闪烁任务栏按钮
    public const uint FLASHW_TRAY = 2;
    // 同时闪烁窗口标题和任务栏按钮
    public const uint FLASHW_ALL = 3;
    //持续闪烁,直到手动停止
    public const uint FLASHW_TIMER = 4;
    // 闪烁直到窗口获得焦点
    public const uint FLASHW_TIMERNOFG = 12;
 
    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool FlashWindowEx(ref FLASHWINFO pwfi);
 
    [StructLayout(LayoutKind.Sequential)]
    private struct FLASHWINFO
    {
        public uint cbSize;
        public IntPtr hwnd;
        public uint dwFlags;
        public uint uCount;
        public uint dwTimeout;
    }
 
    /// <summary>
    /// 任务栏和指定窗口闪烁,直到该窗口获得焦点
    /// </summary>
    /// <param name="window"></param>
    public static bool FlashTaskbarAndWindow(Window window)
    {
        FLASHWINFO fwi = new FLASHWINFO();
        fwi.cbSize = Convert.ToUInt32(Marshal.SizeOf(fwi));
        fwi.dwFlags = FLASHW_ALL | FLASHW_TIMER;
        fwi.uCount = uint.MaxValue;
        fwi.dwTimeout = 0;
 
        if (window == null)
        {
            window = Application.Current.MainWindow;
        }
        var wih = new WindowInteropHelper(window);
        fwi.hwnd = wih.Handle;
 
        return FlashWindowEx(ref fwi);
    }
 
    /// <summary>
    /// 暂停任务栏和指定窗口的闪烁
    /// </summary>
    /// <param name="window"></param>
    public static bool StopFlashing(Window window)
    {
        FLASHWINFO fwi = new FLASHWINFO();
        fwi.cbSize = Convert.ToUInt32(Marshal.SizeOf(fwi));
        fwi.dwFlags = FLASHW_STOP;
        fwi.uCount = uint.MaxValue;
        fwi.dwTimeout = 0;
        if (window == null)
        {
            window = Application.Current.MainWindow;
        }
        var wih = new WindowInteropHelper(window);
        fwi.hwnd = wih.Handle;
        return FlashWindowEx(ref fwi);
    }
}

I have not failed. I've just found 10,000 ways that won't work.