dev 19-3-26

This commit is contained in:
NaBian committed 2019-03-26 23:09:16 +08:00
1 parent ce18931d5d
commit 93c351a308
13 files changed
+141 -225

No files matched your search

+89 -52
View File
@@ -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();
}
}
}
}
}
-3
View File
@@ -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)]
+12 -10
View File
@@ -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
{
+3 -1
View File
@@ -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;
+4 -1
View File
@@ -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);
-21
View File
@@ -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;
}
}
+22 -1
View File
@@ -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);
}
}
+1 -1
View File
@@ -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;
-103
View File
@@ -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>