dev 19-3-25

This commit is contained in:
NaBian committed 2019-03-25 23:50:57 +08:00
1 parent 53228907fc
commit ce18931d5d
29 files changed
+1474 -85

No files matched your search

@@ -0,0 +1,152 @@
using System.Windows;
using System.Windows.Media;
using HandyControl.Data;
using HandyControl.Tools;
using HandyControl.Tools.Interop;
namespace HandyControl.Controls
{
public class NotifyIcon : FrameworkElement
{
private bool _added;
private readonly object _syncObj = new object();
private WindowClass _windowClass;
private readonly int _id;
private static int NextId;
private ImageSource _icon;
private IconHandle _defaultLargeIconHandle;
private IconHandle _defaultSmallIconHandle;
private IconHandle _currentLargeIconHandle;
private IconHandle _currentSmallIconHandle;
private const int WmTrayMouseMessage = NativeMethods.WM_USER + 1024;
public NotifyIcon()
{
_id = ++NextId;
_windowClass = new WindowClass();
}
public static readonly DependencyProperty IconProperty = DependencyProperty.Register(
"Icon", typeof(ImageSource), typeof(NotifyIcon), new PropertyMetadata(default(ImageSource), OnIconChanged));
private static void OnIconChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ctl = (NotifyIcon) d;
ctl._icon = (ImageSource) e.NewValue;
ctl.UpdateIcon();
}
public ImageSource Icon
{
get => (ImageSource) GetValue(IconProperty);
set => SetValue(IconProperty, value);
}
private void UpdateIcon()
{
IconHandle largeIconHandle;
IconHandle smallIconHandle;
if (_icon != null)
{
IconHelper.GetIconHandlesFromImageSource(_icon, out largeIconHandle, out smallIconHandle);
}
else
{
if (_defaultLargeIconHandle == null && _defaultSmallIconHandle == null)
{
IconHelper.GetDefaultIconHandles(out largeIconHandle, out smallIconHandle);
_defaultLargeIconHandle = largeIconHandle;
_defaultSmallIconHandle = smallIconHandle;
}
else
{
largeIconHandle = _defaultLargeIconHandle;
smallIconHandle = _defaultSmallIconHandle;
}
}
if (_currentLargeIconHandle != null && _currentLargeIconHandle != _defaultLargeIconHandle)
{
_currentLargeIconHandle.Dispose();
}
if (_currentSmallIconHandle != null && _currentSmallIconHandle != _defaultSmallIconHandle)
{
_currentSmallIconHandle.Dispose();
}
_currentLargeIconHandle = largeIconHandle;
_currentSmallIconHandle = smallIconHandle;
}
public static readonly DependencyProperty BalloonTipIconProperty = DependencyProperty.Register(
"BalloonTipIcon", typeof(ToolTipIcon), typeof(NotifyIcon), new PropertyMetadata(default(ToolTipIcon)));
public ToolTipIcon BalloonTipIcon
{
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)
{
if (DesignerHelper.IsInDesignMode) return;
IntSecurity.UnrestrictedWindows.Demand();
var data = new NOTIFYICONDATA
{
hWnd = _windowClass.MessageWindowHandle,
uID = _id,
uFlags = NativeMethods.NIF_INFO,
uTimeoutOrVersion = timeout,
szInfoTitle = tipTitle,
szInfo = tipText
};
switch (tipIcon)
{
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;
}
UnsafeNativeMethods.Shell_NotifyIcon(NativeMethods.NIM_MODIFY, data);
}
}
}
}
@@ -0,0 +1,29 @@
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();
}
}
}
}
}
-31
View File
@@ -1,31 +0,0 @@
using System.Windows;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
using HandyControl.Tools;
namespace HandyControl.Controls
{
public class NotifyIcon : FrameworkElement
{
private Popup _trayPopup;
private readonly object _syncObj = new object();
public static readonly DependencyProperty IconProperty = DependencyProperty.Register(
"Icon", typeof(ImageSource), typeof(NotifyIcon), new PropertyMetadata(default(ImageSource)));
public ImageSource Icon
{
get => (ImageSource) GetValue(IconProperty);
set => SetValue(IconProperty, value);
}
private void UpdateIcon(bool showIconInTray)
{
lock (_syncObj)
{
if (DesignerHelper.IsInDesignMode) return;
}
}
}
}
+10
View File
@@ -0,0 +1,10 @@
namespace HandyControl.Data
{
public enum ToolTipIcon
{
None,
Info,
Warning,
Error
}
}
+41
View File
@@ -0,0 +1,41 @@
using HandyControl.Tools.Interop;
using System;
using System.Diagnostics.CodeAnalysis;
namespace HandyControl.Data
{
public sealed class Icon : IDisposable
{
private IntPtr _handle;
~Icon()
{
Dispose(false);
}
internal Icon(IntPtr handle)
{
if (handle == IntPtr.Zero)
{
throw new ArgumentException("InvalidGDIHandle", typeof(Icon).Name);
}
_handle = handle;
}
[SuppressMessage("ReSharper", "UnusedParameter.Local")]
private void Dispose(bool disposing)
{
if (_handle != IntPtr.Zero)
{
UnsafeNativeMethods.DestroyIcon(_handle);
_handle = IntPtr.Zero;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}
+23 -1
View File
@@ -115,8 +115,9 @@
<Compile Include="Controls\Other\ChatBubble.cs" />
<Compile Include="Controls\Other\Dialog.cs" />
<Compile Include="Controls\Other\GotoTop.cs" />
<Compile Include="Controls\Other\NotifyIcon.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" />
@@ -172,11 +173,13 @@
<Compile Include="Data\Enum\SkinType.cs" />
<Compile Include="Data\Enum\StepStatus.cs" />
<Compile Include="Data\Enum\TipPlacement.cs" />
<Compile Include="Data\Enum\ToolTipIcon.cs" />
<Compile Include="Data\Gif\GifFrameDimension.cs" />
<Compile Include="Data\Gif\GifImageInfo.cs" />
<Compile Include="Data\Gif\GifPropertyItem.cs" />
<Compile Include="Data\Gif\GifPropertyItemInternal.cs" />
<Compile Include="Data\Gif\GPStream.cs" />
<Compile Include="Data\Icon.cs" />
<Compile Include="Data\MessageBoxInfo.cs" />
<Compile Include="Data\ResourceToken.cs" />
<Compile Include="Data\SystemVersionInfo.cs" />
@@ -224,8 +227,13 @@
<Compile Include="Expression\Media\UnitType.cs" />
<Compile Include="Expression\Shapes\Arc.cs" />
<Compile Include="Expression\Shapes\PrimitiveShape.cs" />
<Compile Include="Tools\Helper\CreateParams.cs" />
<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" />
<Compile Include="Controls\TabControl\TabControl.cs" />
<Compile Include="Controls\TabControl\TabItem.cs" />
@@ -305,6 +313,20 @@
<Compile Include="Tools\Converter\TreeViewItemMarginConverter.cs" />
<Compile Include="Tools\Extension\ColorExtension.cs" />
<Compile Include="Tools\Extension\UIElementExtension.cs" />
<Compile Include="Tools\Interop\BitmapHandle.cs" />
<Compile Include="Tools\Interop\BITMAPINFO.cs" />
<Compile Include="Tools\Interop\CommonHandles.cs" />
<Compile Include="Tools\Interop\ExternDll.cs" />
<Compile Include="Tools\Interop\HandleCollector.cs" />
<Compile Include="Tools\Interop\IconHandle.cs" />
<Compile Include="Tools\Interop\ICONINFO.cs" />
<Compile Include="Tools\Interop\NativeMethods.cs" />
<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" />
<Compile Include="Tools\StyleSelector\RadioGroupItemStyleSelector.cs" />
<Compile Include="Tools\RegularJudgment.cs" />
+1 -1
View File
@@ -1,4 +1,4 @@
/*refrence from https://github.com/lbugnion/mvvmlight*/
// reference from https://github.com/lbugnion/mvvmlight
//The MIT License(MIT)
+54
View File
@@ -0,0 +1,54 @@
using System;
using System.Text;
namespace HandyControl.Tools
{
internal class CreateParams
{
public string ClassName { get; set; }
public string Caption { get; set; }
public int Style { get; set; }
public int ExStyle{ get; set; }
public int ClassStyle { get; set; }
public int X { get; set; }
public int Y { get; set; }
public int Width { get; set; }
public int Height { get; set; }
public IntPtr Parent { get; set; }
public object Param { get; set; }
public override string ToString()
{
var sb = new StringBuilder(64);
sb.Append("CreateParams {'");
sb.Append(ClassName);
sb.Append("', '");
sb.Append(Caption);
sb.Append("', 0x");
sb.Append(Convert.ToString(Style, 16));
sb.Append(", 0x");
sb.Append(Convert.ToString(ExStyle, 16));
sb.Append(", {");
sb.Append(X);
sb.Append(", ");
sb.Append(Y);
sb.Append(", ");
sb.Append(Width);
sb.Append(", ");
sb.Append(Height);
sb.Append("}");
sb.Append("}");
return sb.ToString();
}
}
}
+1 -50
View File
@@ -17,49 +17,7 @@ namespace HandyControl.Tools
private const string User32 = "user32.dll";
private const string Shell32 = "shell32.dll";
public delegate IntPtr WndProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public class NOTIFYICONDATA
{
public int cbSize = Marshal.SizeOf(typeof(NOTIFYICONDATA));
public IntPtr hWnd;
public int uID;
public int uFlags;
public int uCallbackMessage;
public IntPtr hIcon;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string szTip;
public int dwState = 0;
public int dwStateMask = 0;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string szInfo;
public int uTimeoutOrVersion;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
public string szInfoTitle;
public int dwInfoFlags;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public class WNDCLASS_D
{
public int style;
public WndProc lpfnWndProc;
public int cbClsExtra = 0;
public int cbWndExtra = 0;
public IntPtr hInstance = IntPtr.Zero;
public IntPtr hIcon = IntPtr.Zero;
public IntPtr hCursor = IntPtr.Zero;
public IntPtr hbrBackground = IntPtr.Zero;
public string lpszMenuName = null;
public string lpszClassName = null;
}
[DllImport(Shell32, CharSet = CharSet.Auto)]
[ResourceExposure(ResourceScope.None)]
public static extern int Shell_NotifyIcon(int message, NOTIFYICONDATA pnid);
public delegate IntPtr WndProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
public const int E_FAIL = unchecked((int) 0x80004005);
@@ -114,7 +72,6 @@ namespace HandyControl.Tools
[In]
int len);
int Write(
[In]
IntPtr buf,
@@ -128,7 +85,6 @@ namespace HandyControl.Tools
[In]
int dwOrigin);
void SetSize(
[In, MarshalAs(UnmanagedType.I8)]
long libNewSize);
@@ -142,15 +98,12 @@ namespace HandyControl.Tools
[Out, MarshalAs(UnmanagedType.LPArray)]
long[] pcbRead);
void Commit(
[In]
int grfCommitFlags);
void Revert();
void LockRegion(
[In, MarshalAs(UnmanagedType.I8)]
long libOffset,
@@ -159,7 +112,6 @@ namespace HandyControl.Tools
[In]
int dwLockType);
void UnlockRegion(
[In, MarshalAs(UnmanagedType.I8)]
long libOffset,
@@ -168,7 +120,6 @@ namespace HandyControl.Tools
[In]
int dwLockType);
void Stat(
[In]
IntPtr pStatstg,
+292
View File
@@ -0,0 +1,292 @@
using System;
using System.Collections.ObjectModel;
using System.Runtime.InteropServices;
using System.Security;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using HandyControl.Tools.Interop;
namespace HandyControl.Tools
{
internal static class IconHelper
{
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);
}
[SecurityCritical]
public static IconHandle CreateIconHandleFromImageSource(ImageSource image, Size size)
{
EnsureSystemMetrics();
var asGoodAsItGets = false;
var bf = image as BitmapFrame;
if (bf?.Decoder?.Frames != null)
{
bf = GetBestMatch(bf.Decoder.Frames, size);
asGoodAsItGets = bf.Decoder is IconBitmapDecoder || bf.PixelWidth == (int)size.Width && bf.PixelHeight == (int)size.Height;
image = bf;
}
if (!asGoodAsItGets)
{
bf = BitmapFrame.Create(GenerateBitmapSource(image, size));
}
return CreateIconHandleFromBitmapFrame(bf);
}
[SecurityCritical]
private static IconHandle CreateIconHandleFromBitmapFrame(BitmapFrame sourceBitmapFrame)
{
BitmapSource bitmapSource = sourceBitmapFrame;
if (bitmapSource.Format != PixelFormats.Bgra32 && bitmapSource.Format != PixelFormats.Pbgra32)
{
bitmapSource = new FormatConvertedBitmap(bitmapSource, PixelFormats.Bgra32, null, 0.0);
}
var w = bitmapSource.PixelWidth;
var h = bitmapSource.PixelHeight;
var bpp = bitmapSource.Format.BitsPerPixel;
var stride = (bpp * w + 31) / 32 * 4;
var sizeCopyPixels = stride * h;
var xor = new byte[sizeCopyPixels];
bitmapSource.CopyPixels(xor, stride, 0);
return CreateIconCursor(xor, w, h, 0, 0, true);
}
[SecurityCritical]
internal static IconHandle CreateIconCursor(byte[] colorArray, int width, int height, int xHotspot, int yHotspot, bool isIcon)
{
BitmapHandle colorBitmap = null;
BitmapHandle maskBitmap = null;
try
{
var bi = new BITMAPINFO(width, -height, 32)
{
bmiHeader_biCompression = NativeMethods.BI_RGB
};
var bits = IntPtr.Zero;
colorBitmap = UnsafeNativeMethods.CreateDIBSection(new HandleRef(null, IntPtr.Zero), ref bi, NativeMethods.DIB_RGB_COLORS, ref bits, null, 0);
if (colorBitmap.IsInvalid || bits == IntPtr.Zero)
{
return IconHandle.GetInvalidIcon();
}
Marshal.Copy(colorArray, 0, bits, colorArray.Length);
var maskArray = GenerateMaskArray(width, height, colorArray);
maskBitmap = UnsafeNativeMethods.CreateBitmap(width, height, 1, 1, maskArray);
if (maskBitmap.IsInvalid)
{
return IconHandle.GetInvalidIcon();
}
var iconInfo = new ICONINFO
{
fIcon = isIcon,
xHotspot = xHotspot,
yHotspot = yHotspot,
hbmMask = maskBitmap,
hbmColor = colorBitmap
};
return UnsafeNativeMethods.CreateIconIndirect(iconInfo);
}
finally
{
colorBitmap?.Dispose();
maskBitmap?.Dispose();
}
}
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;
}
internal static int AlignToBytes(double original, int nBytesCount)
{
var nBitsCount = 8 << (nBytesCount - 1);
return ((int)Math.Ceiling(original) + (nBitsCount - 1)) / nBitsCount * nBitsCount;
}
private static BitmapSource GenerateBitmapSource(ImageSource img, Size renderSize)
{
var drawingDimensions = new Rect(0, 0, renderSize.Width, renderSize.Height);
var renderRatio = renderSize.Width / renderSize.Height;
var aspectRatio = img.Width / img.Height;
if (img.Width <= renderSize.Width && img.Height <= renderSize.Height)
{
drawingDimensions = new Rect((renderSize.Width - img.Width) / 2, (renderSize.Height - img.Height) / 2, img.Width, img.Height);
}
else if (renderRatio > aspectRatio)
{
var scaledRenderWidth = (img.Width / img.Height) * renderSize.Width;
drawingDimensions = new Rect((renderSize.Width - scaledRenderWidth) / 2, 0, scaledRenderWidth, renderSize.Height);
}
else if (renderRatio < aspectRatio)
{
var scaledRenderHeight = img.Height / img.Width * renderSize.Height;
drawingDimensions = new Rect(0, (renderSize.Height - scaledRenderHeight) / 2, renderSize.Width, scaledRenderHeight);
}
var dv = new DrawingVisual();
var dc = dv.RenderOpen();
dc.DrawImage(img, drawingDimensions);
dc.Close();
var bmp = new RenderTargetBitmap((int)renderSize.Width, (int)renderSize.Height, 96, 96, PixelFormats.Pbgra32);
bmp.Render(dv);
return bmp;
}
private static BitmapFrame GetBestMatch(ReadOnlyCollection<BitmapFrame> frames, Size size)
{
var bestScore = int.MaxValue;
var bestBpp = 0;
var bestIndex = 0;
var isBitmapIconDecoder = frames[0].Decoder is IconBitmapDecoder;
for (int i = 0; i < frames.Count && bestScore != 0; ++i)
{
var currentIconBitDepth = isBitmapIconDecoder ? frames[i].Thumbnail.Format.BitsPerPixel : frames[i].Format.BitsPerPixel;
if (currentIconBitDepth == 0)
{
currentIconBitDepth = 8;
}
var score = MatchImage(frames[i], size, currentIconBitDepth);
if (score < bestScore)
{
bestIndex = i;
bestBpp = currentIconBitDepth;
bestScore = score;
}
else if (score == bestScore)
{
if (bestBpp < currentIconBitDepth)
{
bestIndex = i;
bestBpp = currentIconBitDepth;
}
}
}
return frames[bestIndex];
}
private static int MatchImage(BitmapFrame frame, Size size, int bpp)
{
var score = 2 * MyAbs(bpp, _systemBitDepth, false) +
MyAbs(frame.PixelWidth, (int)size.Width, true) +
MyAbs(frame.PixelHeight, (int)size.Height, true);
return score;
}
private static int MyAbs(int valueHave, int valueWant, bool fPunish)
{
var diff = (valueHave - valueWant);
if (diff < 0)
{
diff = (fPunish ? -2 : -1) * diff;
}
return diff;
}
[SecurityCritical, SecuritySafeCritical]
private static void EnsureSystemMetrics()
{
if (_systemBitDepth == 0)
{
var hdcDesktop = new HandleRef(null, UnsafeNativeMethods.GetDC(new HandleRef()));
try
{
var sysBitDepth = UnsafeNativeMethods.GetDeviceCaps(hdcDesktop, NativeMethods.BITSPIXEL);
sysBitDepth *= UnsafeNativeMethods.GetDeviceCaps(hdcDesktop, NativeMethods.PLANES);
if (sysBitDepth == 8)
{
sysBitDepth = 4;
}
var cxSmallIcon = UnsafeNativeMethods.GetSystemMetrics(SM.CXSMICON);
var cySmallIcon = UnsafeNativeMethods.GetSystemMetrics(SM.CYSMICON);
var cxIcon = UnsafeNativeMethods.GetSystemMetrics(SM.CXICON);
var cyIcon = UnsafeNativeMethods.GetSystemMetrics(SM.CYICON);
_smallIconSize = new Size(cxSmallIcon, cySmallIcon);
_iconSize = new Size(cxIcon, cyIcon);
_systemBitDepth = sysBitDepth;
}
finally
{
UnsafeNativeMethods.ReleaseDC(new HandleRef(), hdcDesktop);
}
}
}
[SecurityCritical, SecuritySafeCritical]
public static void GetDefaultIconHandles(out IconHandle largeIconHandle, out IconHandle smallIconHandle)
{
largeIconHandle = null;
smallIconHandle = null;
SecurityHelper.DemandUIWindowPermission();
var iconModuleFile = UnsafeNativeMethods.GetModuleFileName(new HandleRef());
UnsafeNativeMethods.ExtractIconEx(iconModuleFile, 0, out largeIconHandle, out smallIconHandle, 1);
}
}
}
@@ -0,0 +1,20 @@
using System.Security;
using System.Security.Permissions;
namespace HandyControl.Tools
{
internal class SecurityHelper
{
private static UIPermission _allWindowsUIPermission;
[SecurityCritical]
internal static void DemandUIWindowPermission()
{
if (_allWindowsUIPermission == null)
{
_allWindowsUIPermission = new UIPermission(UIPermissionWindow.AllWindows);
}
_allWindowsUIPermission.Demand();
}
}
}
+52
View File
@@ -0,0 +1,52 @@
using System.Runtime.InteropServices;
using System.Security;
namespace HandyControl.Tools.Interop
{
[StructLayout(LayoutKind.Sequential, Pack = 2)]
internal struct BITMAPINFO
{
public int bmiHeader_biSize;
public int bmiHeader_biWidth;
public int bmiHeader_biHeight;
public short bmiHeader_biPlanes;
public short bmiHeader_biBitCount;
public int bmiHeader_biCompression;
public int bmiHeader_biSizeImage;
public int bmiHeader_biXPelsPerMeter;
public int bmiHeader_biYPelsPerMeter;
public int bmiHeader_biClrUsed;
public int bmiHeader_biClrImportant;
public BITMAPINFO(int width, int height, short bpp)
{
bmiHeader_biSize = SizeOf();
bmiHeader_biWidth = width;
bmiHeader_biHeight = height;
bmiHeader_biPlanes = 1;
bmiHeader_biBitCount = bpp;
bmiHeader_biCompression = 0;
bmiHeader_biSizeImage = 0;
bmiHeader_biXPelsPerMeter = 0;
bmiHeader_biYPelsPerMeter = 0;
bmiHeader_biClrUsed = 0;
bmiHeader_biClrImportant = 0;
}
[SecuritySafeCritical]
private static int SizeOf()
{
return Marshal.SizeOf(typeof(BITMAPINFO));
}
}
}
@@ -0,0 +1,37 @@
using System;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
namespace HandyControl.Tools.Interop
{
internal sealed class BitmapHandle : WpfSafeHandle
{
[SecurityCritical]
private BitmapHandle(bool ownsHandle) : base(ownsHandle, CommonHandles.GDI)
{
}
[SecurityCritical]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
protected override bool ReleaseHandle()
{
return UnsafeNativeMethods.DeleteObject(handle);
}
[SecurityCritical]
internal HandleRef MakeHandleRef(object obj)
{
return new HandleRef(obj, handle);
}
[SecurityCritical]
internal static BitmapHandle CreateFromHandle(IntPtr hbitmap, bool ownsHandle = true)
{
return new BitmapHandle(ownsHandle)
{
handle = hbitmap,
};
}
}
}
@@ -0,0 +1,13 @@
namespace HandyControl.Tools.Interop
{
internal static class CommonHandles
{
public static readonly int Icon = HandleCollector.RegisterType(nameof(Icon), 20, 500);
public static readonly int HDC = HandleCollector.RegisterType(nameof(HDC), 100, 2);
public static readonly int GDI = HandleCollector.RegisterType(nameof(GDI), 50, 500);
public static readonly int Kernel = HandleCollector.RegisterType(nameof(Kernel), 0, 1000);
}
}
+11
View File
@@ -0,0 +1,11 @@
namespace HandyControl.Tools.Interop
{
internal static class ExternDll
{
public const string
User32 = "user32.dll",
Gdi32 = "gdi32.dll",
Kernel32 = "kernel32.dll",
Shell32 = "shell32.dll";
}
}
@@ -0,0 +1,132 @@
// reference from https://referencesource.microsoft.com/#WindowsBase/Shared/MS/Win32/HandleCollector.cs,d0f99220d8e1b708
using System;
using System.Runtime.InteropServices;
namespace HandyControl.Tools.Interop
{
internal static class HandleCollector
{
private static HandleType[] HandleTypes;
private static int HandleTypeCount;
private static readonly object HandleMutex = new object();
internal static IntPtr Add(IntPtr handle, int type)
{
HandleTypes[type - 1].Add();
return handle;
}
[System.Security.SecuritySafeCritical]
internal static SafeHandle Add(SafeHandle handle, int type)
{
HandleTypes[type - 1].Add();
return handle;
}
internal static void Add(int type)
{
HandleTypes[type - 1].Add();
}
internal static int RegisterType(string typeName, int expense, int initialThreshold)
{
lock (HandleMutex)
{
if (HandleTypeCount == 0 || HandleTypeCount == HandleTypes.Length)
{
HandleType[] newTypes = new HandleType[HandleTypeCount + 10];
if (HandleTypes != null)
{
Array.Copy(HandleTypes, 0, newTypes, 0, HandleTypeCount);
}
HandleTypes = newTypes;
}
HandleTypes[HandleTypeCount++] = new HandleType(expense, initialThreshold);
return HandleTypeCount;
}
}
internal static IntPtr Remove(IntPtr handle, int type)
{
HandleTypes[type - 1].Remove();
return handle;
}
[System.Security.SecuritySafeCritical]
internal static SafeHandle Remove(SafeHandle handle, int type)
{
HandleTypes[type - 1].Remove();
return handle;
}
internal static void Remove(int type)
{
HandleTypes[type - 1].Remove();
}
private class HandleType
{
private readonly int _initialThreshHold;
private int _threshHold;
private int _handleCount;
private readonly int _deltaPercent;
internal HandleType(int expense, int initialThreshHold)
{
_initialThreshHold = initialThreshHold;
_threshHold = initialThreshHold;
_deltaPercent = 100 - expense;
}
internal void Add()
{
lock (this)
{
_handleCount++;
var performCollect = NeedCollection();
if (!performCollect)
{
return;
}
}
GC.Collect();
var sleep = (100 - _deltaPercent) / 4;
System.Threading.Thread.Sleep(sleep);
}
private bool NeedCollection()
{
if (_handleCount > _threshHold)
{
_threshHold = _handleCount + ((_handleCount * _deltaPercent) / 100);
return true;
}
var oldThreshHold = (100 * _threshHold) / (100 + _deltaPercent);
if (oldThreshHold >= _initialThreshHold && _handleCount < (int)(oldThreshHold * .9F))
{
_threshHold = oldThreshHold;
}
return false;
}
internal void Remove()
{
lock (this)
{
_handleCount--;
_handleCount = Math.Max(0, _handleCount);
}
}
}
}
}
+14
View File
@@ -0,0 +1,14 @@
using System.Runtime.InteropServices;
namespace HandyControl.Tools.Interop
{
[StructLayout(LayoutKind.Sequential)]
internal class ICONINFO
{
public bool fIcon = false;
public int xHotspot = 0;
public int yHotspot = 0;
public BitmapHandle hbmMask = null;
public BitmapHandle hbmColor = null;
}
}
+33
View File
@@ -0,0 +1,33 @@
using System;
using System.Runtime.ConstrainedExecution;
using System.Security;
namespace HandyControl.Tools.Interop
{
internal sealed class IconHandle : WpfSafeHandle
{
[SecurityCritical]
private IconHandle() : base(true, CommonHandles.Icon)
{
}
[SecurityCritical]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
protected override bool ReleaseHandle()
{
return UnsafeNativeMethods.DestroyIcon(handle);
}
[SecurityCritical, SecuritySafeCritical]
internal static IconHandle GetInvalidIcon()
{
return new IconHandle();
}
[SecurityCritical]
internal IntPtr CriticalGetHandle()
{
return handle;
}
}
}
+21
View File
@@ -0,0 +1,21 @@
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;
}
}
@@ -0,0 +1,28 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
namespace HandyControl.Tools.Interop
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
[SuppressMessage("ReSharper", "InconsistentNaming")]
public class NOTIFYICONDATA
{
public int cbSize = Marshal.SizeOf(typeof(NOTIFYICONDATA));
public IntPtr hWnd;
public int uID;
public int uFlags;
public int uCallbackMessage;
public IntPtr hIcon;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string szTip;
public int dwState = 0;
public int dwStateMask = 0;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string szInfo;
public int uTimeoutOrVersion;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
public string szInfoTitle;
public int dwInfoFlags;
}
}
@@ -0,0 +1,37 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
namespace HandyControl.Tools.Interop
{
public delegate IntPtr WndProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
[SuppressMessage("ReSharper", "InconsistentNaming")]
[SuppressMessage("ReSharper", "IdentifierTypo")]
internal class NativeMethods
{
public const int
WS_CHILD = 0x40000000,
WM_USER = 0x0400,
BITSPIXEL = 12,
PLANES = 14,
BI_RGB = 0,
DIB_RGB_COLORS = 0,
NIF_MESSAGE = 0x00000001,
NIF_INFO = 0x00000010,
NIF_ICON = 0x00000002,
NIF_TIP = 0x00000004,
NIM_ADD = 0x00000000,
NIM_DELETE = 0x00000002,
NIM_MODIFY = 0x00000001,
NIIF_NONE = 0x00000000,
NIIF_INFO = 0x00000001,
NIIF_WARNING = 0x00000002,
NIIF_ERROR = 0x00000003;
[DllImport(ExternDll.User32, CharSet = CharSet.Auto)]
[ResourceExposure(ResourceScope.None)]
public static extern int RegisterWindowMessage(string msg);
}
}
@@ -0,0 +1,98 @@
namespace HandyControl.Tools.Interop
{
internal enum SM
{
CXSCREEN = 0,
CYSCREEN = 1,
CXVSCROLL = 2,
CYHSCROLL = 3,
CYCAPTION = 4,
CXBORDER = 5,
CYBORDER = 6,
CXFIXEDFRAME = 7,
CYFIXEDFRAME = 8,
CYVTHUMB = 9,
CXHTHUMB = 10,
CXICON = 11,
CYICON = 12,
CXCURSOR = 13,
CYCURSOR = 14,
CYMENU = 15,
CXFULLSCREEN = 16,
CYFULLSCREEN = 17,
CYKANJIWINDOW = 18,
MOUSEPRESENT = 19,
CYVSCROLL = 20,
CXHSCROLL = 21,
DEBUG = 22,
SWAPBUTTON = 23,
CXMIN = 28,
CYMIN = 29,
CXSIZE = 30,
CYSIZE = 31,
CXFRAME = 32,
CXSIZEFRAME = CXFRAME,
CYFRAME = 33,
CYSIZEFRAME = CYFRAME,
CXMINTRACK = 34,
CYMINTRACK = 35,
CXDOUBLECLK = 36,
CYDOUBLECLK = 37,
CXICONSPACING = 38,
CYICONSPACING = 39,
MENUDROPALIGNMENT = 40,
PENWINDOWS = 41,
DBCSENABLED = 42,
CMOUSEBUTTONS = 43,
SECURE = 44,
CXEDGE = 45,
CYEDGE = 46,
CXMINSPACING = 47,
CYMINSPACING = 48,
CXSMICON = 49,
CYSMICON = 50,
CYSMCAPTION = 51,
CXSMSIZE = 52,
CYSMSIZE = 53,
CXMENUSIZE = 54,
CYMENUSIZE = 55,
ARRANGE = 56,
CXMINIMIZED = 57,
CYMINIMIZED = 58,
CXMAXTRACK = 59,
CYMAXTRACK = 60,
CXMAXIMIZED = 61,
CYMAXIMIZED = 62,
NETWORK = 63,
CLEANBOOT = 67,
CXDRAG = 68,
CYDRAG = 69,
SHOWSOUNDS = 70,
CXMENUCHECK = 71,
CYMENUCHECK = 72,
SLOWMACHINE = 73,
MIDEASTENABLED = 74,
MOUSEWHEELPRESENT = 75,
XVIRTUALSCREEN = 76,
YVIRTUALSCREEN = 77,
CXVIRTUALSCREEN = 78,
CYVIRTUALSCREEN = 79,
CMONITORS = 80,
SAMEDISPLAYFORMAT = 81,
IMMENABLED = 82,
CXFOCUSBORDER = 83,
CYFOCUSBORDER = 84,
TABLETPC = 86,
MEDIACENTER = 87,
REMOTESESSION = 0x1000,
REMOTECONTROL = 0x2001,
}
internal static class Win32Constant
{
internal const int MAX_PATH = 260;
internal const int INFOTIPSIZE = 1024;
internal const int TRUE = 1;
internal const int FALSE = 0;
}
}
@@ -0,0 +1,50 @@
using System;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using Microsoft.Win32.SafeHandles;
namespace HandyControl.Tools.Interop
{
internal sealed class SafeFileMappingHandle : SafeHandleZeroOrMinusOneIsInvalid
{
[SecurityCritical]
internal SafeFileMappingHandle(IntPtr handle) : base(false)
{
SetHandle(handle);
}
[SecurityCritical, SecuritySafeCritical]
internal SafeFileMappingHandle() : base(true)
{
}
public override bool IsInvalid
{
[SecurityCritical, SecuritySafeCritical]
get => handle == IntPtr.Zero;
}
[SecurityCritical, SecuritySafeCritical]
protected override bool ReleaseHandle()
{
new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert();
try
{
return CloseHandleNoThrow(new HandleRef(null, handle));
}
finally
{
CodeAccessPermission.RevertAssert();
}
}
[SecurityCritical]
public static bool CloseHandleNoThrow(HandleRef handle)
{
HandleCollector.Remove((IntPtr)handle, CommonHandles.Kernel);
var result = UnsafeNativeMethods.IntCloseHandle(handle);
return result;
}
}
}
@@ -0,0 +1,173 @@
using System;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Text;
namespace HandyControl.Tools.Interop
{
[SuppressMessage("ReSharper", "InconsistentNaming")]
internal class UnsafeNativeMethods
{
[SecurityCritical]
[SuppressUnmanagedCodeSecurity]
[DllImport(ExternDll.User32, SetLastError = true, ExactSpelling = true, EntryPoint = nameof(GetDC), CharSet = CharSet.Auto)]
public static extern IntPtr IntGetDC(HandleRef hWnd);
[SecurityCritical]
public static IntPtr GetDC(HandleRef hWnd)
{
var hDc = IntGetDC(hWnd);
if (hDc == IntPtr.Zero)
{
throw new Win32Exception();
}
return HandleCollector.Add(hDc, CommonHandles.HDC);
}
[SecurityCritical]
[SuppressUnmanagedCodeSecurity]
[DllImport(ExternDll.User32, ExactSpelling = true, EntryPoint = nameof(ReleaseDC), CharSet = CharSet.Auto)]
public static extern int IntReleaseDC(HandleRef hWnd, HandleRef hDC);
[SecurityCritical]
public static int ReleaseDC(HandleRef hWnd, HandleRef hDC)
{
HandleCollector.Remove((IntPtr)hDC, CommonHandles.HDC);
return IntReleaseDC(hWnd, hDC);
}
[SecurityCritical]
[SuppressUnmanagedCodeSecurity]
[DllImport(ExternDll.Gdi32, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Auto)]
public static extern int GetDeviceCaps(HandleRef hDC, int nIndex);
[SecurityCritical]
[SuppressUnmanagedCodeSecurity]
[DllImport(ExternDll.User32)]
public static extern int GetSystemMetrics(SM nIndex);
[SecurityCritical]
[SuppressUnmanagedCodeSecurity]
[DllImport(ExternDll.User32, EntryPoint = nameof(DestroyIcon), CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool IntDestroyIcon(IntPtr hIcon);
[SecurityCritical]
public static bool DestroyIcon(IntPtr hIcon)
{
var result = IntDestroyIcon(hIcon);
return result;
}
[SecurityCritical]
[SuppressUnmanagedCodeSecurity]
[DllImport(ExternDll.Gdi32, EntryPoint = nameof(DeleteObject), CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool IntDeleteObject(IntPtr hObject);
[SecurityCritical]
public static bool DeleteObject(IntPtr hObject)
{
var result = IntDeleteObject(hObject);
return result;
}
[SecurityCritical]
public static BitmapHandle CreateDIBSection(HandleRef hdc, ref BITMAPINFO bitmapInfo, int iUsage, ref IntPtr ppvBits, SafeFileMappingHandle hSection, int dwOffset)
{
if (hSection == null)
{
hSection = new SafeFileMappingHandle(IntPtr.Zero);
}
var hBitmap = PrivateCreateDIBSection(hdc, ref bitmapInfo, iUsage, ref ppvBits, hSection, dwOffset);
return hBitmap;
}
[DllImport(ExternDll.Kernel32, EntryPoint = "CloseHandle", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool IntCloseHandle(HandleRef handle);
[SecurityCritical, SuppressUnmanagedCodeSecurity]
[DllImport(ExternDll.Gdi32, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Auto, EntryPoint = nameof(CreateDIBSection))]
private static extern BitmapHandle PrivateCreateDIBSection(HandleRef hdc, ref BITMAPINFO bitmapInfo, int iUsage, ref IntPtr ppvBits, SafeFileMappingHandle hSection, int dwOffset);
[SecurityCritical, SuppressUnmanagedCodeSecurity]
[DllImport(ExternDll.User32, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Auto, EntryPoint = nameof(CreateIconIndirect))]
private static extern IconHandle PrivateCreateIconIndirect([In, MarshalAs(UnmanagedType.LPStruct)]ICONINFO iconInfo);
[SecurityCritical]
public static IconHandle CreateIconIndirect([In, MarshalAs(UnmanagedType.LPStruct)]ICONINFO iconInfo)
{
var hIcon = PrivateCreateIconIndirect(iconInfo);
return hIcon;
}
[SecurityCritical, SuppressUnmanagedCodeSecurity]
[DllImport(ExternDll.Gdi32, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Auto, EntryPoint = nameof(CreateBitmap))]
private static extern BitmapHandle PrivateCreateBitmap(int width, int height, int planes, int bitsPerPixel, byte[] lpvBits);
[SecurityCritical]
internal static BitmapHandle CreateBitmap(int width, int height, int planes, int bitsPerPixel, byte[] lpvBits)
{
var hBitmap = PrivateCreateBitmap(width, height, planes, bitsPerPixel, lpvBits);
return hBitmap;
}
[SecurityCritical, SuppressUnmanagedCodeSecurity]
[DllImport(ExternDll.Kernel32, EntryPoint = "GetModuleFileName", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern int IntGetModuleFileName(HandleRef hModule, StringBuilder buffer, int length);
[SecurityCritical]
internal static string GetModuleFileName(HandleRef hModule)
{
var buffer = new StringBuilder(Win32Constant.MAX_PATH);
while (true)
{
var size = IntGetModuleFileName(hModule, buffer, buffer.Capacity);
if (size == 0)
{
throw new Win32Exception();
}
if (size == buffer.Capacity)
{
buffer.EnsureCapacity(buffer.Capacity * 2);
continue;
}
return buffer.ToString();
}
}
[SecurityCritical, SuppressUnmanagedCodeSecurity]
[DllImport(ExternDll.Shell32, CharSet = CharSet.Auto, BestFitMapping = false, ThrowOnUnmappableChar = true)]
internal static extern int ExtractIconEx(string szExeFileName, int nIconIndex, out IconHandle phiconLarge, out IconHandle phiconSmall, int nIcons);
[DllImport(ExternDll.Shell32, CharSet = CharSet.Auto)]
[ResourceExposure(ResourceScope.None)]
public static extern int Shell_NotifyIcon(int message, NOTIFYICONDATA pnid);
[SecurityCritical]
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
[DllImport(ExternDll.User32, SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "CreateWindowExW")]
public static extern IntPtr CreateWindowEx(
int dwExStyle,
[MarshalAs(UnmanagedType.LPWStr)] string lpClassName,
[MarshalAs(UnmanagedType.LPWStr)] string lpWindowName,
int dwStyle,
int x,
int y,
int nWidth,
int nHeight,
IntPtr hWndParent,
IntPtr hMenu,
IntPtr hInstance,
IntPtr lpParam);
[DllImport(ExternDll.User32, CharSet = CharSet.Auto, SetLastError = true)]
[ResourceExposure(ResourceScope.None)]
public static extern short RegisterClass(WNDCLASS wc);
}
}
+23
View File
@@ -0,0 +1,23 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
namespace HandyControl.Tools.Interop
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
[SuppressMessage("ReSharper", "InconsistentNaming")]
[SuppressMessage("ReSharper", "IdentifierTypo")]
internal class WNDCLASS
{
public int style;
public ExternDllHelper.WndProc lpfnWndProc;
public int cbClsExtra = 0;
public int cbWndExtra = 0;
public IntPtr hInstance = IntPtr.Zero;
public IntPtr hIcon = IntPtr.Zero;
public IntPtr hCursor = IntPtr.Zero;
public IntPtr hbrBackground = IntPtr.Zero;
public string lpszMenuName = null;
public string lpszClassName = null;
}
}
+103
View File
@@ -0,0 +1,103 @@
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;
//}
}
}
}
}
@@ -0,0 +1,24 @@
using System.Security;
using Microsoft.Win32.SafeHandles;
namespace HandyControl.Tools.Interop
{
internal abstract class WpfSafeHandle : SafeHandleZeroOrMinusOneIsInvalid
{
private readonly int _collectorId;
[SecurityCritical]
protected WpfSafeHandle(bool ownsHandle, int collectorId) : base(ownsHandle)
{
HandleCollector.Add(collectorId);
_collectorId = collectorId;
}
[SecurityCritical, SecuritySafeCritical]
protected override void Dispose(bool disposing)
{
HandleCollector.Remove(_collectorId);
base.Dispose(disposing);
}
}
}
@@ -500,7 +500,7 @@
</data>
<data name="NotifyIcon" xml:space="preserve">
<value>NotifyIcon</value>
<data>
</data>
<data name="Badge" xml:space="preserve">
<value>Badge</value>
</data>
+1 -1
View File
@@ -500,7 +500,7 @@
</data>
<data name="NotifyIcon" xml:space="preserve">
<value>托盘图标</value>
<data>
</data>
<data name="Badge" xml:space="preserve">
<value>标记</value>
</data>