diff --git a/HandyControl/Controls/Other/NotifyIcon.cs b/HandyControl/Controls/Other/NotifyIcon.cs
index eb263959..64c2e802 100644
--- a/HandyControl/Controls/Other/NotifyIcon.cs
+++ b/HandyControl/Controls/Other/NotifyIcon.cs
@@ -5,6 +5,7 @@ using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
+using System.Windows.Threading;
using HandyControl.Data;
using HandyControl.Tools;
using HandyControl.Tools.Interop;
@@ -45,6 +46,10 @@ namespace HandyControl.Controls
private bool _doubleClick;
+ private DispatcherTimer _dispatcherTimer;
+
+ private bool _isTransparent;
+
static NotifyIcon()
{
VisibilityProperty.OverrideMetadata(typeof(NotifyIcon), new PropertyMetadata(Visibility.Visible, OnVisibilityChanged));
@@ -111,6 +116,12 @@ namespace HandyControl.Controls
ctl.OnIconChanged();
}
+ public ImageSource Icon
+ {
+ get => (ImageSource)GetValue(IconProperty);
+ set => SetValue(IconProperty, value);
+ }
+
public static readonly DependencyProperty ContextContentProperty = DependencyProperty.Register(
"ContextContent", typeof(object), typeof(NotifyIcon), new PropertyMetadata(default(object)));
@@ -120,8 +131,56 @@ namespace HandyControl.Controls
set => SetValue(ContextContentProperty, value);
}
+ public static readonly DependencyProperty BlinkIntervalProperty = DependencyProperty.Register(
+ "BlinkInterval", typeof(TimeSpan), typeof(NotifyIcon), new PropertyMetadata(TimeSpan.FromMilliseconds(500), OnBlinkIntervalChanged));
+
+ private static void OnBlinkIntervalChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var ctl = (NotifyIcon)d;
+ if (ctl._dispatcherTimer != null)
+ {
+ ctl._dispatcherTimer.Interval = (TimeSpan) e.NewValue;
+ }
+ }
+
+ public TimeSpan BlinkInterval
+ {
+ get => (TimeSpan) GetValue(BlinkIntervalProperty);
+ set => SetValue(BlinkIntervalProperty, value);
+ }
+
public static readonly DependencyProperty IsBlinkProperty = DependencyProperty.Register(
- "IsBlink", typeof(bool), typeof(NotifyIcon), new PropertyMetadata(ValueBoxes.FalseBox));
+ "IsBlink", typeof(bool), typeof(NotifyIcon), new PropertyMetadata(ValueBoxes.FalseBox, OnIsBlinkChanged));
+
+ private static void OnIsBlinkChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var ctl = (NotifyIcon)d;
+ if (ctl.Visibility != Visibility.Visible) return;
+ if ((bool) e.NewValue)
+ {
+ if (ctl._dispatcherTimer == null)
+ {
+ ctl._dispatcherTimer = new DispatcherTimer
+ {
+ Interval = ctl.BlinkInterval
+ };
+ ctl._dispatcherTimer.Tick += ctl.DispatcherTimer_Tick;
+ }
+ ctl._dispatcherTimer.Start();
+ }
+ else
+ {
+ ctl._dispatcherTimer?.Stop();
+ ctl._dispatcherTimer = null;
+ ctl.UpdateIcon(true);
+ }
+ }
+
+ private void DispatcherTimer_Tick(object sender, EventArgs e)
+ {
+ if (Visibility != Visibility.Visible || _currentSmallIconHandle == null) return;
+ UpdateIcon(true, !_isTransparent);
+ }
public bool IsBlink
{
@@ -129,12 +188,6 @@ namespace HandyControl.Controls
set => SetValue(IsBlinkProperty, value);
}
- public ImageSource Icon
- {
- get => (ImageSource)GetValue(IconProperty);
- set => SetValue(IconProperty, value);
- }
-
private void OnIconChanged()
{
IconHandle largeIconHandle;
@@ -173,12 +226,13 @@ namespace HandyControl.Controls
_currentSmallIconHandle = smallIconHandle;
}
- private void UpdateIcon(bool showIconInTray)
+ private void UpdateIcon(bool showIconInTray, bool isTransparent = false)
{
lock (_syncObj)
{
- if (DesignerHelper.IsInDesignMode) return;
+ if (_currentSmallIconHandle == null || DesignerHelper.IsInDesignMode) return;
+ _isTransparent = isTransparent;
var data = new NOTIFYICONDATA
{
uCallbackMessage = WmTrayMouseMessage,
@@ -187,7 +241,7 @@ namespace HandyControl.Controls
uTimeoutOrVersion = 10,
uID = _id,
dwInfoFlags = NativeMethods.NIF_TIP,
- hIcon = _currentSmallIconHandle.CriticalGetHandle(),
+ hIcon = isTransparent ? IntPtr.Zero : _currentSmallIconHandle.CriticalGetHandle(),
szTip = Text
};
@@ -397,6 +451,10 @@ namespace HandyControl.Controls
{
if (disposing)
{
+ if (_dispatcherTimer != null && IsBlink)
+ {
+ _dispatcherTimer.Stop();
+ }
UpdateIcon(false);
_defaultLargeIconHandle?.Dispose();
_defaultSmallIconHandle?.Dispose();
diff --git a/HandyControl/Tools/Interop/BitmapHandle.cs b/HandyControl/Tools/Interop/BitmapHandle.cs
index 2970e514..1e893fa9 100644
--- a/HandyControl/Tools/Interop/BitmapHandle.cs
+++ b/HandyControl/Tools/Interop/BitmapHandle.cs
@@ -1,12 +1,20 @@
using System;
+using System.Diagnostics.CodeAnalysis;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
namespace HandyControl.Tools.Interop
{
+ [SuppressMessage("ReSharper", "UnusedMember.Local")]
internal sealed class BitmapHandle : WpfSafeHandle
{
+ [SecurityCritical]
+ private BitmapHandle() : this(true)
+ {
+ //请不要删除此构造函数,否则当使用自定义ico文件时会报错
+ }
+
[SecurityCritical]
private BitmapHandle(bool ownsHandle) : base(ownsHandle, CommonHandles.GDI)
{
diff --git a/HandyControlDemo/HandyControlDemo.csproj b/HandyControlDemo/HandyControlDemo.csproj
index 53deb9f4..cbbb9f37 100644
--- a/HandyControlDemo/HandyControlDemo.csproj
+++ b/HandyControlDemo/HandyControlDemo.csproj
@@ -805,6 +805,7 @@
TextTemplatingFileGenerator
MessageToken.cs
+
diff --git a/HandyControlDemo/Resources/Img/icon-white.ico b/HandyControlDemo/Resources/Img/icon-white.ico
new file mode 100644
index 00000000..a90a5b46
Binary files /dev/null and b/HandyControlDemo/Resources/Img/icon-white.ico differ
diff --git a/HandyControlDemo/Resources/Img/icon-white.png b/HandyControlDemo/Resources/Img/icon-white.png
deleted file mode 100644
index d0bb4776..00000000
Binary files a/HandyControlDemo/Resources/Img/icon-white.png and /dev/null differ
diff --git a/HandyControlDemo/UserControl/Controls/NotifyIconDemoCtl.xaml b/HandyControlDemo/UserControl/Controls/NotifyIconDemoCtl.xaml
index 3b701d5d..15ab993d 100644
--- a/HandyControlDemo/UserControl/Controls/NotifyIconDemoCtl.xaml
+++ b/HandyControlDemo/UserControl/Controls/NotifyIconDemoCtl.xaml
@@ -6,20 +6,32 @@
xmlns:interactivity="clr-namespace:HandyControl.Interactivity;assembly=HandyControl"
DataContext="{Binding NotifyIconDemo,Source={StaticResource Locator}}"
Background="{DynamicResource RegionBrush}">
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
+
@@ -27,5 +39,18 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/HandyControlDemo/ViewModel/Controls/NotifyIconDemoViewModel.cs b/HandyControlDemo/ViewModel/Controls/NotifyIconDemoViewModel.cs
index d2e48bc5..2a40d6af 100644
--- a/HandyControlDemo/ViewModel/Controls/NotifyIconDemoViewModel.cs
+++ b/HandyControlDemo/ViewModel/Controls/NotifyIconDemoViewModel.cs
@@ -5,16 +5,44 @@ namespace HandyControlDemo.ViewModel
{
public class NotifyIconDemoViewModel : ViewModelBase
{
- private bool _isShow;
+ private bool _contextMenuIsShow;
- public bool IsShow
+ public bool ContextMenuIsShow
{
- get => _isShow;
+ get => _contextMenuIsShow;
set
{
- Set(ref _isShow, value);
- GlobalData.NotifyIconIsShow = value;
+ Set(ref _contextMenuIsShow, value);
+ GlobalData.NotifyIconIsShow = ContextMenuIsShow || ContextContentIsShow;
}
}
+
+ private bool _contextMenuIsBlink;
+
+ public bool ContextMenuIsBlink
+ {
+ get => _contextMenuIsBlink;
+ set => Set(ref _contextMenuIsBlink, value);
+ }
+
+ private bool _contextContentIsShow;
+
+ public bool ContextContentIsShow
+ {
+ get => _contextContentIsShow;
+ set
+ {
+ Set(ref _contextContentIsShow, value);
+ GlobalData.NotifyIconIsShow = ContextMenuIsShow || ContextContentIsShow;
+ }
+ }
+
+ private bool _contextContentIsBlink;
+
+ public bool ContextContentIsBlink
+ {
+ get => _contextContentIsBlink;
+ set => Set(ref _contextContentIsBlink, value);
+ }
}
}
\ No newline at end of file