前言
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;
}
});
}
总结
随便写写,但是关键代码一行不少,有问题下面提哈