2021-01-14

前言

WPF仿钉钉在通知栏icon的功能,包括消息提示(图标闪烁),鼠标移动事件,判断鼠标是否在ICON上面等待


提示:仅提供关键代码

一、使用到的User32函数、字段、枚举(获取ICON信息)

代码如下(示例):

        [DllImport("user32.dll")]
        public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);
        [DllImport("user32.dll")]
        private static extern bool GetWindowRect(IntPtr hwnd, out Rect lpRect);
        [DllImport("User32.dll")]
        private static extern IntPtr WindowFromPoint(POINT p);
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern bool GetCursorPos(out POINT pt);
        /// <summary>
        /// 不同操作系统偏移量
        /// </summary>
        private int py = 0;

        private const int WM_USER = 0x400;
        private const int TB_GETBUTTONSIZE = WM_USER + 58;
    [StructLayout(LayoutKind.Sequential)]
    public struct POINT
    {
        public int X;
        public int Y;

        public POINT(int x, int y)
        {
            this.X = x;
            this.Y = y;
        }

        public override string ToString()
        {
            return ("X:" + X + ", Y:" + Y);
        }
    }

二、获取ICON信息

代码如下(示例):

    /// <summary>
    /// 程序托盘区图标位置
    /// </summary>
    public class IconInfo
    {
        /// <summary>
        /// 托盘区句柄
        /// </summary>
        public IntPtr hWnd = IntPtr.Zero;
        /// <summary>
        /// 图标X坐标
        /// </summary>
        public int X;
        /// <summary>
        /// 图标Y坐标
        /// </summary>
        public int Y;
        /// <summary>
        /// 图标宽度
        /// </summary>
        public int Width;
        /// <summary>
        /// 图标高度
        /// </summary>
        public int Height;
        public bool InIconRect(POINT p)
        {
            if (p.X >= X && p.X <= X + Width && p.Y >= Y && p.Y <= Y + Height)
            {
                return true;
            }
            return false;
        }
    }

2.读入数据

代码如下(示例):

    /// <summary>
        /// 图标信息
        /// </summary>
        private IconInfo MyIcon = new IconInfo();
            /// <summary>
        /// 在鼠标移动事件中调用
        /// </summary>
        private void GetIconInfo()
        {
            POINT currentPoint = new POINT();
            GetCursorPos(out currentPoint);
            MyIcon.hWnd = WindowFromPoint(currentPoint);
            int BtnSize = SendMessage(MyIcon.hWnd, TB_GETBUTTONSIZE, IntPtr.Zero, IntPtr.Zero);
            MyIcon.Width = BtnSize & 0xFFFF;
            MyIcon.Height = (BtnSize / 0x10000) & 0xFFFF;
            Rect rect = new Rect();
            if (GetWindowRect(MyIcon.hWnd, out rect))
            {
                if (MyIcon.Width != 0 && MyIcon.Height != 0)
                {
                    MyIcon.X =(int)( (currentPoint.X - rect.Left - py) / MyIcon.Width * MyIcon.Width + rect.Left + py);
                    MyIcon.Y =(int) ((currentPoint.Y - rect.Top - py) / MyIcon.Height * MyIcon.Height + rect.Top + py);
                }
            }
        }

三、引用类库wpf-notifyicon

代码如下(示例):
项目地址 http://www.hardcodet.net/projects/wpf-notifyicon,里面有个WPF示例,有基本的通知栏操作示例,下面的代码是其没有的功能

           //图标闪烁动画
           Storyboard storyboard = new Storyboard();
            ObjectAnimationUsingKeyFrames oaukf = new ObjectAnimationUsingKeyFrames();
            //资源    <BitmapImage x:Key="TaskbarIcon_logo" UriSource="/logo.ico" />
            DiscreteObjectKeyFrame dokf1 = new DiscreteObjectKeyFrame((BitmapImage)FindResource("TaskbarIcon_logo"), TimeSpan.FromSeconds(0));
            DiscreteObjectKeyFrame dokf2 = new DiscreteObjectKeyFrame(null, TimeSpan.FromSeconds(0.5));
            DiscreteObjectKeyFrame dokf3 = new DiscreteObjectKeyFrame((BitmapImage)FindResource("TaskbarIcon_logo"), TimeSpan.FromSeconds(1));
            oaukf.KeyFrames.Add(dokf1);
            oaukf.KeyFrames.Add(dokf2);
            oaukf.KeyFrames.Add(dokf3);
            storyboard.Children.Add(oaukf);

            Storyboard.SetTarget(oaukf, App.notifyIcon);
            Storyboard.SetTargetProperty(oaukf, new PropertyPath("IconSource"));

            storyboard.RepeatBehavior = RepeatBehavior.Forever;
            storyboard.Begin();
            //这儿是增加像钉钉那个鼠标放上去就弹出消息的功能
            grid = (TextBox)FindResource("test");//这儿是消息框资源,自己重写
            App.notifyIcon.TrayPopup = grid;
            //这个地方处理鼠标mouseOver相关
            App.notifyIcon.TrayMouseMove += NotifyIcon_TrayMouseMove1;
     private void NotifyIcon_TrayMouseMove1(object sender, RoutedEventArgs e)
        {
            if (!App.notifyIcon.TrayPopupResolved.IsOpen)
            {
                App.notifyIcon.TrayPopupResolved.Placement = System.Windows.Controls.Primitives.PlacementMode.Mouse;
                App.notifyIcon.TrayPopupResolved.IsOpen = true;
                App.notifyIcon.TrayPopupResolved.StaysOpen = false;
            }
            //鼠标移动时不断更新IconInfo
            GetIconInfo();
        }
//定时器,处理当鼠标离开ICON时,去除消息弹窗
 private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            this.Dispatcher.Invoke(() =>
            {
                POINT currentPoint = new POINT();
                GetCursorPos(out currentPoint);
                if (MyIcon!=null&& !MyIcon.InIconRect(currentPoint) && App.notifyIcon.TrayPopupResolved!=null)
                {
                     App.notifyIcon.TrayPopupResolved.IsOpen = false;
                }
            });
        }

总结

随便写写,但是关键代码一行不少,有问题下面提哈

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值