dev 19-3-26
This commit is contained in:
1 parent
ce18931d5d
commit
93c351a308
13 files changed
+141
-225
No files matched your search
@@ -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 });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -117,7 +117,6 @@
|
||||
<Compile Include="Controls\Other\GotoTop.cs" />
|
||||
<Compile Include="Controls\NotifyIcon\NotifyIcon.cs" />
|
||||
<Compile Include="Controls\Other\Gravatar.cs" />
|
||||
<Compile Include="Controls\NotifyIcon\NotifyIconNativeWindow.cs" />
|
||||
<Compile Include="Controls\Panel\SimplePanel.cs" />
|
||||
<Compile Include="Controls\ProgressBar\WaveProgressBar.cs" />
|
||||
<Compile Include="Controls\Transfer\Transfer.cs" />
|
||||
@@ -231,7 +230,6 @@
|
||||
<Compile Include="Tools\Helper\DesignerHelper.cs" />
|
||||
<Compile Include="Tools\Helper\ExternDllHelper.cs" />
|
||||
<Compile Include="Tools\Helper\IconHelper.cs" />
|
||||
<Compile Include="Tools\Interop\IntSecurity.cs" />
|
||||
<Compile Include="Tools\Interop\NOTIFYICONDATA.cs" />
|
||||
<Compile Include="Tools\Helper\SecurityHelper.cs" />
|
||||
<Compile Include="Tools\Helper\SingleOpenHelper.cs" />
|
||||
@@ -324,7 +322,6 @@
|
||||
<Compile Include="Tools\Interop\NativeValues.cs" />
|
||||
<Compile Include="Tools\Interop\SafeFileMappingHandle.cs" />
|
||||
<Compile Include="Tools\Interop\UnsafeNativeMethods.cs" />
|
||||
<Compile Include="Tools\Interop\WindowClass.cs" />
|
||||
<Compile Include="Tools\Interop\WNDCLASS.cs" />
|
||||
<Compile Include="Tools\Interop\WpfSafeHandle.cs" />
|
||||
<Compile Include="Tools\MouseDragElementBehaviorEx.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)]
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<CodeAccessPermission>(() => AllWindows).Value;
|
||||
|
||||
public static CodeAccessPermission AllWindows =>
|
||||
new Lazy<CodeAccessPermission>(() => new UIPermission(UIPermissionWindow.AllWindows)).Value;
|
||||
|
||||
public static CodeAccessPermission CreateAnyWindow =>
|
||||
new Lazy<CodeAccessPermission>(() => SafeSubWindows).Value;
|
||||
|
||||
public static CodeAccessPermission SafeSubWindows =>
|
||||
new Lazy<CodeAccessPermission>(() => new UIPermission(UIPermissionWindow.SafeSubWindows)).Value;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
<UserControl x:Class="HandyControlDemo.UserControl.NotifyIconDemoCtl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="clr-namespace:HandyControl.Controls;assembly=HandyControl"
|
||||
Background="{DynamicResource RegionBrush}">
|
||||
<Grid>
|
||||
|
||||
<controls:NotifyIcon Text="123" BalloonTipText="123" BalloonTipTitle="123"/>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
Reference in new issue
Block a user