前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >WPF实现基础控件之托盘的示例代码分享

WPF实现基础控件之托盘的示例代码分享

原创
作者头像
用户7718188
发布2022-11-06 20:15:57
6340
发布2022-11-06 20:15:57
举报
文章被收录于专栏:高级工程司高级工程司

WPF 基础控件之托盘

框架使用大于等于.NET40

Visual Studio 2022

项目使用?MIT?开源许可协议。

新建NotifyIcon自定义控件继承自FrameworkElement

创建托盘程序主要借助与?Win32API:

  • 注册窗体对象RegisterClassEx
  • 注册消息获取对应消息标识Id RegisterWindowMessage
  • 创建窗体(本质上托盘在创建时需要一个窗口句柄,完全可以将主窗体的句柄给进去,但是为了更好的管理消息以及托盘的生命周期,通常会创建一个独立不可见的窗口)CreateWindowEx

以下2点需要注意:

  • 托盘控件的ContextMenu菜单MenuItem?在使用binding时无效,是因为DataContext没有带过去,需要重新赋值一次。
  • 托盘控件发送ShowBalloonTip消息通知时候需新建Shell_NotifyIcon
  • Nuget 最新?Install-Package WPFDevelopers 1.0.9.1-preview

1)?NotifyIcon.cs?代码如下:

using?System;

using?System.IO;

using?System.Runtime.InteropServices;

using?System.Threading;

using?System.Windows;

using?System.Windows.Controls;

using?System.Windows.Controls.Primitives;

using?System.Windows.Data;

using?System.Windows.Input;

using?System.Windows.Media;

using?System.Windows.Media.Imaging;

using?WPFDevelopers.Controls.Runtimes;

using?WPFDevelopers.Controls.Runtimes.Interop;

using?WPFDevelopers.Controls.Runtimes.Shell32;

using?WPFDevelopers.Controls.Runtimes.User32;

namespace?WPFDevelopers.Controls

{

????public?class?NotifyIcon?:?FrameworkElement,?IDisposable

????{

????????private?static?NotifyIcon?NotifyIconCache;

????????public?static?readonly?DependencyProperty?ContextContentProperty?=?DependencyProperty.Register(

????????????"ContextContent",?typeof(object),?typeof(NotifyIcon),?new?PropertyMetadata(default));

????????public?static?readonly?DependencyProperty?IconProperty?=

????????????DependencyProperty.Register("Icon",?typeof(ImageSource),?typeof(NotifyIcon),

????????????????new?PropertyMetadata(default,?OnIconPropertyChanged));

????????public?static?readonly?DependencyProperty?TitleProperty?=

????????????DependencyProperty.Register("Title",?typeof(string),?typeof(NotifyIcon),

????????????????new?PropertyMetadata(default,?OnTitlePropertyChanged));

????????public?static?readonly?RoutedEvent?ClickEvent?=

????????????EventManager.RegisterRoutedEvent("Click",?RoutingStrategy.Bubble,

????????????????typeof(RoutedEventHandler),?typeof(NotifyIcon));

????????public?static?readonly?RoutedEvent?MouseDoubleClickEvent?=

????????????EventManager.RegisterRoutedEvent("MouseDoubleClick",?RoutingStrategy.Bubble,

????????????????typeof(RoutedEventHandler),?typeof(NotifyIcon));

????????private?static?bool?s_Loaded?=?false;

????????private?static?NotifyIcon?s_NotifyIcon;

????????//这是窗口名称

????????private?readonly?string?_TrayWndClassName;

????????//这个是窗口消息名称

????????private?readonly?string?_TrayWndMessage;

????????//这个是窗口消息回调(窗口消息都需要在此捕获)

????????private?readonly?WndProc?_TrayWndProc;

????????private?Popup?_contextContent;

????????private?bool?_doubleClick;

????????//图标句柄

????????private?IntPtr?_hIcon?=?IntPtr.Zero;

????????private?ImageSource?_icon;

????????private?IntPtr?_iconHandle;

????????private?int?_IsShowIn;

????????//托盘对象

????????private?NOTIFYICONDATA?_NOTIFYICONDATA;

????????//这个是传递给托盘的鼠标消息id

????????private?int?_TrayMouseMessage;

????????//窗口句柄

????????private?IntPtr?_TrayWindowHandle?=?IntPtr.Zero;

????????//通过注册窗口消息可以获取唯一标识Id

????????private?int?_WmTrayWindowMessage;

????????private?bool?disposedValue;

????????public?NotifyIcon()

????????{

????????????_TrayWndClassName?=?$"WPFDevelopers_{Guid.NewGuid()}";

????????????_TrayWndProc?=?WndProc_CallBack;

????????????_TrayWndMessage?=?"TrayWndMessageName";

????????????_TrayMouseMessage?=?(int)WM.USER?+?1024;

????????????Start();

????????????if?(Application.Current?!=?null)

????????????{

????????????????//Application.Current.MainWindow.Closed?+=?(s,?e)?=>?Dispose();

????????????????Application.Current.Exit?+=?(s,?e)?=>?Dispose();

????????????}

????????????NotifyIconCache?=?this;

????????}

????????static?NotifyIcon()

????????{

????????????DataContextProperty.OverrideMetadata(typeof(NotifyIcon),?new?FrameworkPropertyMetadata(DataContextPropertyChanged));

????????????ContextMenuProperty.OverrideMetadata(typeof(NotifyIcon),?new?FrameworkPropertyMetadata(ContextMenuPropertyChanged));

????????}

????????private?static?void?DataContextPropertyChanged(DependencyObject?d,?DependencyPropertyChangedEventArgs?e)?=>

????????????((NotifyIcon)d).OnDataContextPropertyChanged(e);

????????private?void?OnDataContextPropertyChanged(DependencyPropertyChangedEventArgs?e)

????????{

????????????UpdateDataContext(_contextContent,?e.OldValue,?e.NewValue);

????????????UpdateDataContext(ContextMenu,?e.OldValue,?e.NewValue);

????????}

????????private?void?UpdateDataContext(FrameworkElement?target,?object?oldValue,?object?newValue)

????????{

????????????if?(target?==?null?||?BindingOperations.GetBindingExpression(target,?DataContextProperty)?!=?null)?return;

????????????if?(ReferenceEquals(this,?target.DataContext)?||?Equals(oldValue,?target.DataContext))

????????????{

????????????????target.DataContext?=?newValue????this;

????????????}

????????}

????????private?static?void?ContextMenuPropertyChanged(DependencyObject?d,?DependencyPropertyChangedEventArgs?e)

????????{

????????????var?ctl?=?(NotifyIcon)d;

????????????ctl.OnContextMenuPropertyChanged(e);

????????}

????????private?void?OnContextMenuPropertyChanged(DependencyPropertyChangedEventArgs?e)?=>

????????????UpdateDataContext((ContextMenu)e.NewValue,?null,?DataContext);

????????public?object?ContextContent

????????{

????????????get?=>?GetValue(ContextContentProperty);

????????????set?=>?SetValue(ContextContentProperty,?value);

????????}

????????public?ImageSource?Icon

????????{

????????????get?=>?(ImageSource)GetValue(IconProperty);

????????????set?=>?SetValue(IconProperty,?value);

????????}

????????public?string?Title

????????{

????????????get?=>?(string)GetValue(TitleProperty);

????????????set?=>?SetValue(TitleProperty,?value);

????????}

????????public?void?Dispose()

????????{

????????????Dispose(true);

????????????GC.SuppressFinalize(this);

????????}

????????private?static?void?OnTitlePropertyChanged(DependencyObject?d,?DependencyPropertyChangedEventArgs?e)

????????{

????????????if?(d?is?NotifyIcon?trayService)

????????????????trayService.ChangeTitle(e.NewValue?.ToString());

????????}

????????private?static?void?OnIconPropertyChanged(DependencyObject?d,?DependencyPropertyChangedEventArgs?e)

????????{

????????????if?(d?is?NotifyIcon?trayService)

????????????{

????????????????var?notifyIcon?=?(NotifyIcon)d;

????????????????notifyIcon._icon?=?(ImageSource)e.NewValue;

????????????????trayService.ChangeIcon();

????????????}

????????}

????????public?event?RoutedEventHandler?Click

????????{

????????????add?=>?AddHandler(ClickEvent,?value);

????????????remove?=>?RemoveHandler(ClickEvent,?value);

????????}

????????public?event?RoutedEventHandler?MouseDoubleClick

????????{

????????????add?=>?AddHandler(MouseDoubleClickEvent,?value);

????????????remove?=>?RemoveHandler(MouseDoubleClickEvent,?value);

????????}

????????private?static?void?Current_Exit(object?sender,?ExitEventArgs?e)

????????{

????????????s_NotifyIcon?.Dispose();

????????????s_NotifyIcon?=?default;

????????}

????????public?bool?Start()

????????{

????????????RegisterClass(_TrayWndClassName,?_TrayWndProc,?_TrayWndMessage);

????????????LoadNotifyIconData(string.Empty);

????????????Show();

????????????return?true;

????????}

????????public?bool?Stop()

????????{

????????????//销毁窗体

????????????if?(_TrayWindowHandle?!=?IntPtr.Zero)

????????????????if?(User32Interop.IsWindow(_TrayWindowHandle))

????????????????????User32Interop.DestroyWindow(_TrayWindowHandle);

????????????//反注册窗口类

????????????if?(!string.IsNullOrWhiteSpace(_TrayWndClassName))

????????????????User32Interop.UnregisterClassName(_TrayWndClassName,?Kernel32Interop.GetModuleHandle(default));

????????????//销毁Icon

????????????if?(_hIcon?!=?IntPtr.Zero)

????????????????User32Interop.DestroyIcon(_hIcon);

????????????Hide();

????????????return?true;

????????}

????????///?<summary>

????????///?????注册并创建窗口对象

????????///?</summary>

????????///?<param?name="className">窗口名称</param>

????????///?<param?name="messageName">窗口消息名称</param>

????????///?<returns></returns>

????????private?bool?RegisterClass(string?className,?WndProc?wndproccallback,?string?messageName)

????????{

????????????var?wndClass?=?new?WNDCLASSEX

????????????{

????????????????cbSize?=?Marshal.SizeOf(typeof(WNDCLASSEX)),

????????????????style?=?0,

????????????????lpfnWndProc?=?wndproccallback,

????????????????cbClsExtra?=?0,

????????????????cbWndExtra?=?0,

????????????????hInstance?=?IntPtr.Zero,

????????????????hCursor?=?IntPtr.Zero,

????????????????hbrBackground?=?IntPtr.Zero,

????????????????lpszMenuName?=?string.Empty,

????????????????lpszClassName?=?className

????????????};

????????????//注册窗体对象

????????????User32Interop.RegisterClassEx(ref?wndClass);

????????????//注册消息获取对应消息标识id

????????????_WmTrayWindowMessage?=?User32Interop.RegisterWindowMessage(messageName);

????????????//创建窗体(本质上托盘在创建时需要一个窗口句柄,完全可以将主窗体的句柄给进去,但是为了更好的管理消息以及托盘的生命周期,通常会创建一个独立不可见的窗口)

????????????_TrayWindowHandle?=?User32Interop.CreateWindowEx(0,?className,?"",?0,?0,?0,?1,?1,?IntPtr.Zero,?IntPtr.Zero,

????????????????IntPtr.Zero,?IntPtr.Zero);

????????????return?true;

????????}

????????///?<summary>

????????///?????创建托盘对象

????????///?</summary>

????????///?<param?name="icon">图标路径,可以修改托盘图标(本质上是可以接受用户传入一个图片对象,然后将图片转成Icon,但是算了这个有点复杂)</param>

????????///?<param?name="title">托盘的tooltip</param>

????????///?<returns></returns>

????????private?bool?LoadNotifyIconData(string?title)

????????{

????????????lock?(this)

????????????{

????????????????_NOTIFYICONDATA?=?NOTIFYICONDATA.GetDefaultNotifyData(_TrayWindowHandle);

????????????????if?(_TrayMouseMessage?!=?0)

????????????????????_NOTIFYICONDATA.uCallbackMessage?=?(uint)_TrayMouseMessage;

????????????????else

????????????????????_TrayMouseMessage?=?(int)_NOTIFYICONDATA.uCallbackMessage;

????????????????if?(_iconHandle?==?IntPtr.Zero)

????????????????{

????????????????????var?processPath?=?Kernel32Interop.GetModuleFileName(new?HandleRef());

????????????????????if?(!string.IsNullOrWhiteSpace(processPath))

????????????????????{

????????????????????????var?index?=?IntPtr.Zero;

????????????????????????var?hIcon?=?Shell32Interop.ExtractAssociatedIcon(IntPtr.Zero,?processPath,?ref?index);

????????????????????????_NOTIFYICONDATA.hIcon?=?hIcon;

????????????????????????_hIcon?=?hIcon;

????????????????????}

????????????????}

????????????????if?(!string.IsNullOrWhiteSpace(title))

????????????????????_NOTIFYICONDATA.szTip?=?title;

????????????}

????????????return?true;

????????}

????????private?bool?Show()

????????{

????????????var?command?=?NotifyCommand.NIM_Add;

????????????if?(Thread.VolatileRead(ref?_IsShowIn)?==?1)

????????????????command?=?NotifyCommand.NIM_Modify;

????????????else

????????????????Thread.VolatileWrite(ref?_IsShowIn,?1);

????????????lock?(this)

????????????{

????????????????return?Shell32Interop.Shell_NotifyIcon(command,?ref?_NOTIFYICONDATA);

????????????}

????????}

????????internal?static?int?AlignToBytes(double?original,?int?nBytesCount)

????????{

????????????var?nBitsCount?=?8?<<?(nBytesCount?-?1);

????????????return?((int)Math.Ceiling(original)?+?(nBitsCount?-?1))?/?nBitsCount?*?nBitsCount;

????????}

????????private?static?byte[]?GenerateMaskArray(int?width,?int?height,?byte[]?colorArray)

????????{

????????????var?nCount?=?width?*?height;

????????????var?bytesPerScanLine?=?AlignToBytes(width,?2)?/?8;

????????????var?bitsMask?=?new?byte[bytesPerScanLine?*?height];

????????????for?(var?i?=?0;?i?<?nCount;?i++)

????????????{

????????????????var?hPos?=?i?%?width;

????????????????var?vPos?=?i?/?width;

????????????????var?byteIndex?=?hPos?/?8;

????????????????var?offsetBit?=?(byte)(0x80?>>?(hPos?%?8));

????????????????if?(colorArray[i?*?4?+?3]?==?0x00)

????????????????????bitsMask[byteIndex?+?bytesPerScanLine?*?vPos]?|=?offsetBit;

????????????????else

????????????????????bitsMask[byteIndex?+?bytesPerScanLine?*?vPos]?&=?(byte)~offsetBit;

????????????????if?(hPos?==?width?-?1?&&?width?==?8)?bitsMask[1?+?bytesPerScanLine?*?vPos]?=?0xff;

????????????}

????????????return?bitsMask;

????????}

????????private?byte[]?BitmapImageToByteArray(BitmapImage?bmp)

????????{

????????????byte[]?bytearray?=?null;

????????????try

????????????{

????????????????var?smarket?=?bmp.StreamSource;

????????????????if?(smarket?!=?null?&&?smarket.Length?>?0)

????????????????{

????????????????????//设置当前位置

????????????????????smarket.Position?=?0;

????????????????????using?(var?br?=?new?BinaryReader(smarket))

????????????????????{

????????????????????????bytearray?=?br.ReadBytes((int)smarket.Length);

????????????????????}

????????????????}

????????????}

????????????catch?(Exception?ex)

????????????{

????????????}

????????????return?bytearray;

????????}

????????private?byte[]?ConvertBitmapSourceToBitmapImage(

????????????BitmapSource?bitmapSource)

????????{

????????????byte[]?imgByte?=?default;

????????????if?(!(bitmapSource?is?BitmapImage?bitmapImage))

????????????{

????????????????bitmapImage?=?new?BitmapImage();

????????????????var?encoder?=?new?BmpBitmapEncoder();

????????????????encoder.Frames.Add(BitmapFrame.Create(bitmapSource));

????????????????using?(var?memoryStream?=?new?MemoryStream())

????????????????{

????????????????????encoder.Save(memoryStream);

????????????????????memoryStream.Position?=?0;

????????????????????bitmapImage.BeginInit();

????????????????????bitmapImage.CacheOption?=?BitmapCacheOption.OnLoad;

????????????????????bitmapImage.StreamSource?=?memoryStream;

????????????????????bitmapImage.EndInit();

????????????????????imgByte?=?BitmapImageToByteArray(bitmapImage);

????????????????}

????????????}

????????????return?imgByte;

????????}

????????internal?static?IconHandle?CreateIconCursor(byte[]?xor,?int?width,?int?height,?int?xHotspot,

????????????int?yHotspot,?bool?isIcon)

????????{

????????????var?bits?=?IntPtr.Zero;

????????????BitmapHandle?colorBitmap?=?null;

????????????var?bi?=?new?BITMAPINFO(width,?-height,?32)

????????????{

????????????????bmiHeader_biCompression?=?0

????????????};

????????????colorBitmap?=?Gdi32Interop.CreateDIBSection(new?HandleRef(null,?IntPtr.Zero),?ref?bi,?0,?ref?bits,?null,?0);

????????????if?(colorBitmap.IsInvalid?||?bits?==?IntPtr.Zero)?return?IconHandle.GetInvalidIcon();

????????????Marshal.Copy(xor,?0,?bits,?xor.Length);

????????????var?maskArray?=?GenerateMaskArray(width,?height,?xor);

????????????var?maskBitmap?=?Gdi32Interop.CreateBitmap(width,?height,?1,?1,?maskArray);

????????????if?(maskBitmap.IsInvalid)?return?IconHandle.GetInvalidIcon();

????????????var?iconInfo?=?new?Gdi32Interop.ICONINFO

????????????{

????????????????fIcon?=?isIcon,

????????????????xHotspot?=?xHotspot,

????????????????yHotspot?=?yHotspot,

????????????????hbmMask?=?maskBitmap,

????????????????hbmColor?=?colorBitmap

????????????};

????????????return?User32Interop.CreateIconIndirect(iconInfo);

????????}

????????private?bool?ChangeIcon()

????????{

????????????var?bitmapFrame?=?_icon?as?BitmapFrame;

????????????if?(bitmapFrame?!=?null?&&?bitmapFrame.Decoder?!=?null)

????????????????if?(bitmapFrame.Decoder?is?IconBitmapDecoder)

????????????????{

????????????????????//var?iconBitmapDecoder?=?new?Rect(0,?0,?_icon.Width,?_icon.Height);

????????????????????//var?dv?=?new?DrawingVisual();

????????????????????//var?dc?=?dv.RenderOpen();

????????????????????//dc.DrawImage(_icon,?iconBitmapDecoder);

????????????????????//dc.Close();

????????????????????//var?bmp?=?new?RenderTargetBitmap((int)_icon.Width,?(int)_icon.Height,?96,?96,

????????????????????//????PixelFormats.Pbgra32);

????????????????????//bmp.Render(dv);

????????????????????//BitmapSource?bitmapSource?=?bmp;

????????????????????//if?(bitmapSource.Format?!=?PixelFormats.Bgra32?&&?bitmapSource.Format?!=?PixelFormats.Pbgra32)

????????????????????//????bitmapSource?=?new?FormatConvertedBitmap(bitmapSource,?PixelFormats.Bgra32,?null,?0.0);

????????????????????var?w?=?bitmapFrame.PixelWidth;

????????????????????var?h?=?bitmapFrame.PixelHeight;

????????????????????var?bpp?=?bitmapFrame.Format.BitsPerPixel;

????????????????????var?stride?=?(bpp?*?w?+?31)?/?32?*?4;

????????????????????var?sizeCopyPixels?=?stride?*?h;

????????????????????var?xor?=?new?byte[sizeCopyPixels];

????????????????????bitmapFrame.CopyPixels(xor,?stride,?0);

????????????????????var?iconHandle?=?CreateIconCursor(xor,?w,?h,?0,?0,?true);

????????????????????_iconHandle?=?iconHandle.CriticalGetHandle();

????????????????}

????????????if?(Thread.VolatileRead(ref?_IsShowIn)?!=?1)

????????????????return?false;

????????????if?(_hIcon?!=?IntPtr.Zero)

????????????{

????????????????User32Interop.DestroyIcon(_hIcon);

????????????????_hIcon?=?IntPtr.Zero;

????????????}

????????????lock?(this)

????????????{

????????????????if?(_iconHandle?!=?IntPtr.Zero)

????????????????{

????????????????????var?hIcon?=?_iconHandle;

????????????????????_NOTIFYICONDATA.hIcon?=?hIcon;

????????????????????_hIcon?=?hIcon;

????????????????}

????????????????else

????????????????{

????????????????????_NOTIFYICONDATA.hIcon?=?IntPtr.Zero;

????????????????}

????????????????return?Shell32Interop.Shell_NotifyIcon(NotifyCommand.NIM_Modify,?ref?_NOTIFYICONDATA);

????????????}

????????}

????????private?bool?ChangeTitle(string?title)

????????{

????????????if?(Thread.VolatileRead(ref?_IsShowIn)?!=?1)

????????????????return?false;

????????????lock?(this)

????????????{

????????????????_NOTIFYICONDATA.szTip?=?title;

????????????????return?Shell32Interop.Shell_NotifyIcon(NotifyCommand.NIM_Modify,?ref?_NOTIFYICONDATA);

????????????}

????????}

????????public?static?void?ShowBalloonTip(string?title,?string?content,?NotifyIconInfoType?infoType)

????????{

????????????if?(NotifyIconCache?!=?null)

????????????????NotifyIconCache.ShowBalloonTips(title,?content,?infoType);

????????}

????????public?void?ShowBalloonTips(string?title,?string?content,?NotifyIconInfoType?infoType)

????????{

????????????if?(Thread.VolatileRead(ref?_IsShowIn)?!=?1)

????????????????return;

????????????var?_ShowNOTIFYICONDATA?=?NOTIFYICONDATA.GetDefaultNotifyData(_TrayWindowHandle);

????????????_ShowNOTIFYICONDATA.uFlags?=?NIFFlags.NIF_INFO;

????????????_ShowNOTIFYICONDATA.szInfoTitle?=?title????string.Empty;

????????????_ShowNOTIFYICONDATA.szInfo?=?content????string.Empty;

????????????switch?(infoType)

????????????{

????????????????case?NotifyIconInfoType.Info:

????????????????????_ShowNOTIFYICONDATA.dwInfoFlags?=?NIIFFlags.NIIF_INFO;

????????????????????break;

????????????????case?NotifyIconInfoType.Warning:

????????????????????_ShowNOTIFYICONDATA.dwInfoFlags?=?NIIFFlags.NIIF_WARNING;

????????????????????break;

????????????????case?NotifyIconInfoType.Error:

????????????????????_ShowNOTIFYICONDATA.dwInfoFlags?=?NIIFFlags.NIIF_ERROR;

????????????????????break;

????????????????case?NotifyIconInfoType.None:

????????????????????_ShowNOTIFYICONDATA.dwInfoFlags?=?NIIFFlags.NIIF_NONE;

????????????????????break;

????????????}

????????????Shell32Interop.Shell_NotifyIcon(NotifyCommand.NIM_Modify,?ref?_ShowNOTIFYICONDATA);

????????}

????????private?bool?Hide()

????????{

????????????var?isShow?=?Thread.VolatileRead(ref?_IsShowIn);

????????????if?(isShow?!=?1)

????????????????return?true;

????????????Thread.VolatileWrite(ref?_IsShowIn,?0);

????????????lock?(this)

????????????{

????????????????return?Shell32Interop.Shell_NotifyIcon(NotifyCommand.NIM_Delete,?ref?_NOTIFYICONDATA);

????????????}

????????}

????????private?IntPtr?WndProc_CallBack(IntPtr?hwnd,?WM?msg,?IntPtr?wParam,?IntPtr?lParam)

????????{

????????????//这是窗口相关的消息

????????????if?((int)msg?==?_WmTrayWindowMessage)

????????????{

????????????}

????????????else?if?((int)msg?==?_TrayMouseMessage)?//这是托盘上鼠标相关的消息

????????????{

????????????????switch?((WM)(long)lParam)

????????????????{

????????????????????case?WM.LBUTTONDOWN:

????????????????????????break;

????????????????????case?WM.LBUTTONUP:

????????????????????????WMMouseUp(MouseButton.Left);

????????????????????????break;

????????????????????case?WM.LBUTTONDBLCLK:

????????????????????????WMMouseDown(MouseButton.Left,?2);

????????????????????????break;

????????????????????case?WM.RBUTTONDOWN:

????????????????????????break;

????????????????????case?WM.RBUTTONUP:

????????????????????????OpenMenu();

????????????????????????break;

????????????????????case?WM.MOUSEMOVE:

????????????????????????break;

????????????????????case?WM.MOUSEWHEEL:

????????????????????????break;

????????????????}

????????????}

????????????else?if?(msg?==?WM.COMMAND)

????????????{

????????????}

????????????return?User32Interop.DefWindowProc(hwnd,?msg,?wParam,?lParam);

????????}

????????private?void?WMMouseUp(MouseButton?button)

????????{

????????????if?(!_doubleClick?&&?button?==?MouseButton.Left)

????????????????RaiseEvent(new?MouseButtonEventArgs(

????????????????????Mouse.PrimaryDevice,

????????????????????Environment.TickCount,?button)

????????????????{

????????????????????RoutedEvent?=?ClickEvent

????????????????});

????????????_doubleClick?=?false;

????????}

????????private?void?WMMouseDown(MouseButton?button,?int?clicks)

????????{

????????????if?(clicks?==?2)

????????????{

????????????????RaiseEvent(new?MouseButtonEventArgs(

????????????????????Mouse.PrimaryDevice,

????????????????????Environment.TickCount,?button)

????????????????{

????????????????????RoutedEvent?=?MouseDoubleClickEvent

????????????????});

????????????????_doubleClick?=?true;

????????????}

????????}

????????private?void?OpenMenu()

????????{

????????????if?(ContextContent?!=?null)

????????????{

????????????????_contextContent?=?new?Popup

????????????????{

????????????????????Placement?=?PlacementMode.Mouse,

????????????????????AllowsTransparency?=?true,

????????????????????StaysOpen?=?false,

????????????????????UseLayoutRounding?=?true,

????????????????????SnapsToDevicePixels?=?true

????????????????};

????????????????_contextContent.Child?=?new?ContentControl

????????????????{

????????????????????Content?=?ContextContent

????????????????};

????????????????UpdateDataContext(_contextContent,?null,?DataContext);

????????????????_contextContent.IsOpen?=?true;

????????????????User32Interop.SetForegroundWindow(_contextContent.Child.GetHandle());

????????????}

????????????else?if?(ContextMenu?!=?null)

????????????{

????????????????if?(ContextMenu.Items.Count?==?0)?return;

????????????????ContextMenu.InvalidateProperty(StyleProperty);

????????????????foreach?(var?item?in?ContextMenu.Items)

????????????????????if?(item?is?MenuItem?menuItem)

????????????????????{

????????????????????????menuItem.InvalidateProperty(StyleProperty);

????????????????????}

????????????????????else

????????????????????{

????????????????????????var?container?=?ContextMenu.ItemContainerGenerator.ContainerFromItem(item)?as?MenuItem;

????????????????????????container?.InvalidateProperty(StyleProperty);

????????????????????}

????????????????ContextMenu.Placement?=?PlacementMode.Mouse;

????????????????ContextMenu.IsOpen?=?true;

????????????????User32Interop.SetForegroundWindow(ContextMenu.GetHandle());

????????????}

????????}

????????protected?virtual?void?Dispose(bool?disposing)

????????{

????????????if?(!disposedValue)

????????????{

????????????????if?(disposing)

????????????????????Stop();

????????????????disposedValue?=?true;

????????????}

????????}

????}

????public?enum?NotifyIconInfoType

????{

????????///?<summary>

????????///?????No?Icon.

????????///?</summary>

????????None,

????????///?<summary>

????????///?????A?Information?Icon.

????????///?</summary>

????????Info,

????????///?<summary>

????????///?????A?Warning?Icon.

????????///?</summary>

????????Warning,

????????///?<summary>

????????///?????A?Error?Icon.

????????///?</summary>

????????Error

????}

}

3)?NotifyIconExample.cs?代码如下:

?private?void?Quit_Click(object?sender,?RoutedEventArgs?e)

????????{

????????????Application.Current.Shutdown();

????????}

????????private?void?SendMessage_Click(object?sender,?RoutedEventArgs?e)

????????{

????????????NotifyIcon.ShowBalloonTip("Message",?"?Welcome?to?WPFDevelopers.Minimal?",?NotifyIconInfoType.None);

????????}

ContextContent?使用如下:

?private?void?Quit_Click(object?sender,?RoutedEventArgs?e)

????????{

????????????Application.Current.Shutdown();

????????}

????????private?void?SendMessage_Click(object?sender,?RoutedEventArgs?e)

????????{

????????????NotifyIcon.ShowBalloonTip("Message",?"?Welcome?to?WPFDevelopers.Minimal?",?NotifyIconInfoType.None);

????????}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com