diff --git a/HandyControl/Controls/NotifyIcon/NotifyIcon.cs b/HandyControl/Controls/NotifyIcon/NotifyIcon.cs
index a2717693..c2a6713d 100644
--- a/HandyControl/Controls/NotifyIcon/NotifyIcon.cs
+++ b/HandyControl/Controls/NotifyIcon/NotifyIcon.cs
@@ -1,6 +1,9 @@
-using System.Windows;
+using System;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Controls.Primitives;
+using System.Windows.Data;
using System.Windows.Media;
-using HandyControl.Data;
using HandyControl.Tools;
using HandyControl.Tools.Interop;
@@ -12,8 +15,6 @@ namespace HandyControl.Controls
private readonly object _syncObj = new object();
- private WindowClass _windowClass;
-
private readonly int _id;
private static int NextId;
@@ -30,10 +31,24 @@ namespace HandyControl.Controls
private const int WmTrayMouseMessage = NativeMethods.WM_USER + 1024;
+ private string _windowClassName;
+
+ private static readonly int WmTaskbarcreated = NativeMethods.RegisterWindowMessage("TaskbarCreated");
+
+ private IntPtr _messageWindowHandle;
+
+ private readonly WndProc _callback;
+
+ private ToolTip _toolTip;
+
public NotifyIcon()
{
_id = ++NextId;
- _windowClass = new WindowClass();
+ _callback = Callback;
+ CreateToolTip();
+ RegisterClass();
+ OnIconChanged();
+ UpdateIcon(true);
}
public static readonly DependencyProperty IconProperty = DependencyProperty.Register(
@@ -43,7 +58,7 @@ namespace HandyControl.Controls
{
var ctl = (NotifyIcon) d;
ctl._icon = (ImageSource) e.NewValue;
- ctl.UpdateIcon();
+ ctl.OnIconChanged();
}
public ImageSource Icon
@@ -52,7 +67,7 @@ namespace HandyControl.Controls
set => SetValue(IconProperty, value);
}
- private void UpdateIcon()
+ private void OnIconChanged()
{
IconHandle largeIconHandle;
IconHandle smallIconHandle;
@@ -90,63 +105,85 @@ namespace HandyControl.Controls
_currentSmallIconHandle = smallIconHandle;
}
- public static readonly DependencyProperty BalloonTipIconProperty = DependencyProperty.Register(
- "BalloonTipIcon", typeof(ToolTipIcon), typeof(NotifyIcon), new PropertyMetadata(default(ToolTipIcon)));
-
- public ToolTipIcon BalloonTipIcon
+ private void UpdateIcon(bool showIconInTray)
{
- get => (ToolTipIcon) GetValue(BalloonTipIconProperty);
- set => SetValue(BalloonTipIconProperty, value);
- }
-
- public static readonly DependencyProperty BalloonTipTitleProperty = DependencyProperty.Register(
- "BalloonTipTitle", typeof(string), typeof(NotifyIcon), new PropertyMetadata(default(string)));
-
- public string BalloonTipTitle
- {
- get => (string) GetValue(BalloonTipTitleProperty);
- set => SetValue(BalloonTipTitleProperty, value);
- }
-
- public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
- "Text", typeof(string), typeof(NotifyIcon), new PropertyMetadata(default(string)));
-
- public string Text
- {
- get => (string) GetValue(TextProperty);
- set => SetValue(TextProperty, value);
- }
-
- public void ShowBalloonTip(int timeout, string tipTitle, string tipText, ToolTipIcon tipIcon)
- {
- if (timeout < 0) return;
- if (string.IsNullOrEmpty(tipTitle)) return;
-
- if (_added)
+ lock (_syncObj)
{
if (DesignerHelper.IsInDesignMode) return;
- IntSecurity.UnrestrictedWindows.Demand();
-
var data = new NOTIFYICONDATA
{
- hWnd = _windowClass.MessageWindowHandle,
+ uCallbackMessage = WmTrayMouseMessage,
+ uFlags = NativeMethods.NIF_MESSAGE | NativeMethods.NIF_ICON | NativeMethods.NIF_TIP,
+ hWnd = _messageWindowHandle,
uID = _id,
- uFlags = NativeMethods.NIF_INFO,
- uTimeoutOrVersion = timeout,
- szInfoTitle = tipTitle,
- szInfo = tipText
+ dwInfoFlags = NativeMethods.NIIF_INFO,
+ hIcon = _currentSmallIconHandle.CriticalGetHandle()
};
- switch (tipIcon)
+ if (showIconInTray)
{
- case ToolTipIcon.Info: data.dwInfoFlags = NativeMethods.NIIF_INFO; break;
- case ToolTipIcon.Warning: data.dwInfoFlags = NativeMethods.NIIF_WARNING; break;
- case ToolTipIcon.Error: data.dwInfoFlags = NativeMethods.NIIF_ERROR; break;
- case ToolTipIcon.None: data.dwInfoFlags = NativeMethods.NIIF_NONE; break;
+ if (!_added)
+ {
+ UnsafeNativeMethods.Shell_NotifyIcon(NativeMethods.NIM_ADD, data);
+ _added = true;
+ }
+ else
+ {
+ UnsafeNativeMethods.Shell_NotifyIcon(NativeMethods.NIM_MODIFY, data);
+ }
+ }
+ else if (_added)
+ {
+ UnsafeNativeMethods.Shell_NotifyIcon(NativeMethods.NIM_DELETE, data);
+ _added = false;
}
- UnsafeNativeMethods.Shell_NotifyIcon(NativeMethods.NIM_MODIFY, data);
}
}
+
+ private void RegisterClass()
+ {
+ _windowClassName = $"HandyControl.Controls.NotifyIcon{Guid.NewGuid()}";
+ var wndclass = new WNDCLASS
+ {
+ style = 0,
+ lpfnWndProc = _callback,
+ cbClsExtra = 0,
+ cbWndExtra = 0,
+ hInstance = IntPtr.Zero,
+ hIcon = IntPtr.Zero,
+ hCursor = IntPtr.Zero,
+ hbrBackground = IntPtr.Zero,
+ lpszMenuName = string.Empty,
+ lpszClassName = _windowClassName
+ };
+
+ UnsafeNativeMethods.RegisterClass(wndclass);
+ _messageWindowHandle = UnsafeNativeMethods.CreateWindowEx(0, _windowClassName, "", 0, 0, 0, 1, 1, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
+ }
+
+ private IntPtr Callback(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam)
+ {
+ if (msg == WmTaskbarcreated)
+ {
+ UpdateIcon(true);
+ }
+
+ return UnsafeNativeMethods.DefWindowProc(hWnd, msg, wparam, lparam);
+ }
+
+ private void CreateToolTip()
+ {
+ _toolTip = new ToolTip
+ {
+ Placement = PlacementMode.Mouse,
+ HasDropShadow = false,
+ BorderThickness = new Thickness(0),
+ Background = Brushes.Transparent
+ };
+
+ _toolTip.SetBinding(ContentControl.ContentProperty, new Binding(ToolTipProperty.Name) {Source = this});
+ _toolTip.SetBinding(DataContextProperty, new Binding(DataContextProperty.Name) { Source = this });
+ }
}
}
\ No newline at end of file
diff --git a/HandyControl/Controls/NotifyIcon/NotifyIconNativeWindow.cs b/HandyControl/Controls/NotifyIcon/NotifyIconNativeWindow.cs
deleted file mode 100644
index 1bcf1a11..00000000
--- a/HandyControl/Controls/NotifyIcon/NotifyIconNativeWindow.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-using System.Runtime.InteropServices;
-
-namespace HandyControl.Controls
-{
- internal class NotifyIconNativeWindow
- {
- internal NotifyIcon Reference;
-
- private GCHandle _rootRef;
-
- public void LockReference(bool locked)
- {
- if (locked)
- {
- if (!_rootRef.IsAllocated)
- {
- _rootRef = GCHandle.Alloc(Reference, GCHandleType.Normal);
- }
- }
- else
- {
- if (_rootRef.IsAllocated)
- {
- _rootRef.Free();
- }
- }
- }
- }
-}
\ No newline at end of file
diff --git a/HandyControl/HandyControl.csproj b/HandyControl/HandyControl.csproj
index b4fcfd7b..31a32fbf 100644
--- a/HandyControl/HandyControl.csproj
+++ b/HandyControl/HandyControl.csproj
@@ -117,7 +117,6 @@
-
@@ -231,7 +230,6 @@
-
@@ -324,7 +322,6 @@
-
diff --git a/HandyControl/Tools/Helper/ExternDllHelper.cs b/HandyControl/Tools/Helper/ExternDllHelper.cs
index 858885dc..58264b24 100644
--- a/HandyControl/Tools/Helper/ExternDllHelper.cs
+++ b/HandyControl/Tools/Helper/ExternDllHelper.cs
@@ -17,8 +17,6 @@ namespace HandyControl.Tools
private const string User32 = "user32.dll";
- public delegate IntPtr WndProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
-
public const int E_FAIL = unchecked((int) 0x80004005);
[StructLayout(LayoutKind.Sequential)]
diff --git a/HandyControl/Tools/Helper/IconHelper.cs b/HandyControl/Tools/Helper/IconHelper.cs
index a45b146c..afecc130 100644
--- a/HandyControl/Tools/Helper/IconHelper.cs
+++ b/HandyControl/Tools/Helper/IconHelper.cs
@@ -11,16 +11,18 @@ namespace HandyControl.Tools
{
internal static class IconHelper
{
- private static Size _smallIconSize;
- private static Size _iconSize;
- private static int _systemBitDepth;
+ private static Size SmallIconSize;
+
+ private static Size IconSize;
+
+ private static int SystemBitDepth;
[SecurityCritical, SecuritySafeCritical]
public static void GetIconHandlesFromImageSource(ImageSource image, out IconHandle largeIconHandle, out IconHandle smallIconHandle)
{
EnsureSystemMetrics();
- largeIconHandle = CreateIconHandleFromImageSource(image, _iconSize);
- smallIconHandle = CreateIconHandleFromImageSource(image, _smallIconSize);
+ largeIconHandle = CreateIconHandleFromImageSource(image, IconSize);
+ smallIconHandle = CreateIconHandleFromImageSource(image, SmallIconSize);
}
[SecurityCritical]
@@ -226,7 +228,7 @@ namespace HandyControl.Tools
private static int MatchImage(BitmapFrame frame, Size size, int bpp)
{
- var score = 2 * MyAbs(bpp, _systemBitDepth, false) +
+ var score = 2 * MyAbs(bpp, SystemBitDepth, false) +
MyAbs(frame.PixelWidth, (int)size.Width, true) +
MyAbs(frame.PixelHeight, (int)size.Height, true);
@@ -248,7 +250,7 @@ namespace HandyControl.Tools
[SecurityCritical, SecuritySafeCritical]
private static void EnsureSystemMetrics()
{
- if (_systemBitDepth == 0)
+ if (SystemBitDepth == 0)
{
var hdcDesktop = new HandleRef(null, UnsafeNativeMethods.GetDC(new HandleRef()));
try
@@ -266,9 +268,9 @@ namespace HandyControl.Tools
var cxIcon = UnsafeNativeMethods.GetSystemMetrics(SM.CXICON);
var cyIcon = UnsafeNativeMethods.GetSystemMetrics(SM.CYICON);
- _smallIconSize = new Size(cxSmallIcon, cySmallIcon);
- _iconSize = new Size(cxIcon, cyIcon);
- _systemBitDepth = sysBitDepth;
+ SmallIconSize = new Size(cxSmallIcon, cySmallIcon);
+ IconSize = new Size(cxIcon, cyIcon);
+ SystemBitDepth = sysBitDepth;
}
finally
{
diff --git a/HandyControl/Tools/Interop/BITMAPINFO.cs b/HandyControl/Tools/Interop/BITMAPINFO.cs
index 4a803564..4938fbdd 100644
--- a/HandyControl/Tools/Interop/BITMAPINFO.cs
+++ b/HandyControl/Tools/Interop/BITMAPINFO.cs
@@ -1,9 +1,11 @@
-using System.Runtime.InteropServices;
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.InteropServices;
using System.Security;
namespace HandyControl.Tools.Interop
{
[StructLayout(LayoutKind.Sequential, Pack = 2)]
+ [SuppressMessage("ReSharper", "InconsistentNaming")]
internal struct BITMAPINFO
{
public int bmiHeader_biSize;
diff --git a/HandyControl/Tools/Interop/CommonHandles.cs b/HandyControl/Tools/Interop/CommonHandles.cs
index deb2a7f5..9a61a221 100644
--- a/HandyControl/Tools/Interop/CommonHandles.cs
+++ b/HandyControl/Tools/Interop/CommonHandles.cs
@@ -1,5 +1,8 @@
-namespace HandyControl.Tools.Interop
+using System.Diagnostics.CodeAnalysis;
+
+namespace HandyControl.Tools.Interop
{
+ [SuppressMessage("ReSharper", "InconsistentNaming")]
internal static class CommonHandles
{
public static readonly int Icon = HandleCollector.RegisterType(nameof(Icon), 20, 500);
diff --git a/HandyControl/Tools/Interop/IntSecurity.cs b/HandyControl/Tools/Interop/IntSecurity.cs
deleted file mode 100644
index 679ddaa4..00000000
--- a/HandyControl/Tools/Interop/IntSecurity.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-using System;
-using System.Security;
-using System.Security.Permissions;
-
-namespace HandyControl.Tools.Interop
-{
- internal class IntSecurity
- {
- public static CodeAccessPermission UnrestrictedWindows =>
- new Lazy(() => AllWindows).Value;
-
- public static CodeAccessPermission AllWindows =>
- new Lazy(() => new UIPermission(UIPermissionWindow.AllWindows)).Value;
-
- public static CodeAccessPermission CreateAnyWindow =>
- new Lazy(() => SafeSubWindows).Value;
-
- public static CodeAccessPermission SafeSubWindows =>
- new Lazy(() => new UIPermission(UIPermissionWindow.SafeSubWindows)).Value;
- }
-}
\ No newline at end of file
diff --git a/HandyControl/Tools/Interop/NativeValues.cs b/HandyControl/Tools/Interop/NativeValues.cs
index 628123f7..67796c7a 100644
--- a/HandyControl/Tools/Interop/NativeValues.cs
+++ b/HandyControl/Tools/Interop/NativeValues.cs
@@ -1,4 +1,8 @@
-namespace HandyControl.Tools.Interop
+// ReSharper disable InconsistentNaming
+
+using System.Runtime.InteropServices;
+
+namespace HandyControl.Tools.Interop
{
internal enum SM
{
@@ -95,4 +99,21 @@
internal const int TRUE = 1;
internal const int FALSE = 0;
}
+
+ [StructLayout(LayoutKind.Sequential)]
+ public class POINT
+ {
+ public int x;
+ public int y;
+
+ public POINT()
+ {
+ }
+
+ public POINT(int x, int y)
+ {
+ this.x = x;
+ this.y = y;
+ }
+ }
}
\ No newline at end of file
diff --git a/HandyControl/Tools/Interop/UnsafeNativeMethods.cs b/HandyControl/Tools/Interop/UnsafeNativeMethods.cs
index ed6eb2a4..6d472e5a 100644
--- a/HandyControl/Tools/Interop/UnsafeNativeMethods.cs
+++ b/HandyControl/Tools/Interop/UnsafeNativeMethods.cs
@@ -169,5 +169,13 @@ namespace HandyControl.Tools.Interop
[DllImport(ExternDll.User32, CharSet = CharSet.Auto, SetLastError = true)]
[ResourceExposure(ResourceScope.None)]
public static extern short RegisterClass(WNDCLASS wc);
+
+ [DllImport(ExternDll.User32, CharSet = CharSet.Auto)]
+ [ResourceExposure(ResourceScope.None)]
+ public static extern IntPtr DefWindowProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
+
+ [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = CharSet.Auto)]
+ [ResourceExposure(ResourceScope.None)]
+ public static extern bool GetCursorPos([In, Out] POINT pt);
}
}
\ No newline at end of file
diff --git a/HandyControl/Tools/Interop/WNDCLASS.cs b/HandyControl/Tools/Interop/WNDCLASS.cs
index 363d083f..1fef93ed 100644
--- a/HandyControl/Tools/Interop/WNDCLASS.cs
+++ b/HandyControl/Tools/Interop/WNDCLASS.cs
@@ -10,7 +10,7 @@ namespace HandyControl.Tools.Interop
internal class WNDCLASS
{
public int style;
- public ExternDllHelper.WndProc lpfnWndProc;
+ public WndProc lpfnWndProc;
public int cbClsExtra = 0;
public int cbWndExtra = 0;
public IntPtr hInstance = IntPtr.Zero;
diff --git a/HandyControl/Tools/Interop/WindowClass.cs b/HandyControl/Tools/Interop/WindowClass.cs
deleted file mode 100644
index db49dc77..00000000
--- a/HandyControl/Tools/Interop/WindowClass.cs
+++ /dev/null
@@ -1,103 +0,0 @@
-using System;
-using System.Security.Permissions;
-
-namespace HandyControl.Tools.Interop
-{
- [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
- internal class WindowClass
- {
- internal string WindowClassName;
-
- private static readonly int WmTaskbarcreated = NativeMethods.RegisterWindowMessage("TaskbarCreated");
-
- internal IntPtr MessageWindowHandle { get; private set; }
-
- private readonly object _syncObj = new object();
-
- private bool _added;
-
- public WindowClass()
- {
- RegisterClass();
- }
-
- private void RegisterClass()
- {
- WindowClassName = $"HandyControl.Controls.NotifyIcon{Guid.NewGuid()}";
- var wndclass = new WNDCLASS
- {
- style = 0,
- lpfnWndProc = Callback,
- cbClsExtra = 0,
- cbWndExtra = 0,
- hInstance = IntPtr.Zero,
- hIcon = IntPtr.Zero,
- hCursor = IntPtr.Zero,
- hbrBackground = IntPtr.Zero,
- lpszMenuName = string.Empty,
- lpszClassName = WindowClassName
- };
-
- UnsafeNativeMethods.RegisterClass(wndclass);
- MessageWindowHandle = UnsafeNativeMethods.CreateWindowEx(0, WindowClassName, "", 0, 0, 0, 1, 1, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
- }
-
- public IntPtr Callback(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam)
- {
- if (msg == WmTaskbarcreated)
- {
- _added = false;
- AddIcon();
- }
- return IntPtr.Zero;
- }
-
- private void AddIcon()
- {
- lock (_syncObj)
- {
- if (DesignerHelper.IsInDesignMode) return;
-
- //NativeMethods.NOTIFYICONDATA data = new NativeMethods.NOTIFYICONDATA();
- //data.uCallbackMessage = WM_TRAYMOUSEMESSAGE;
- //data.uFlags = NativeMethods.NIF_MESSAGE;
- //if (showIconInTray)
- //{
- // if (window.Handle == IntPtr.Zero)
- // {
- // window.CreateHandle(new CreateParams());
- // }
- //}
- //data.hWnd = window.Handle;
- //data.uID = id;
- //data.hIcon = IntPtr.Zero;
- //data.szTip = null;
- //if (icon != null)
- //{
- // data.uFlags |= NativeMethods.NIF_ICON;
- // data.hIcon = icon.Handle;
- //}
- //data.uFlags |= NativeMethods.NIF_TIP;
- //data.szTip = text;
-
- //if (showIconInTray && icon != null)
- //{
- // if (!added)
- // {
- // UnsafeNativeMethods.Shell_NotifyIcon(NativeMethods.NIM_ADD, data);
- // added = true;
- // }
- // else
- // {
- // UnsafeNativeMethods.Shell_NotifyIcon(NativeMethods.NIM_MODIFY, data);
- // }
- //}
- //else if (added)
- //{
- // UnsafeNativeMethods.Shell_NotifyIcon(NativeMethods.NIM_DELETE, data);
- // added = false;
- //}
- }
- }
- }
-}
\ No newline at end of file
diff --git a/HandyControlDemo/UserControl/Controls/NotifyIconDemoCtl.xaml b/HandyControlDemo/UserControl/Controls/NotifyIconDemoCtl.xaml
index dc1085aa..6f055fe8 100644
--- a/HandyControlDemo/UserControl/Controls/NotifyIconDemoCtl.xaml
+++ b/HandyControlDemo/UserControl/Controls/NotifyIconDemoCtl.xaml
@@ -1,8 +1,9 @@
-
+