add function codes
This commit is contained in:
1 parent
cae862d6b0
commit
c1d6e901b2
31 files changed
+2428
-169
No files matched your search
@@ -0,0 +1,69 @@
|
||||
using System;
|
||||
|
||||
namespace HandyControl.Data
|
||||
{
|
||||
public class DisposableObject : IDisposable
|
||||
{
|
||||
private EventHandler _disposing;
|
||||
|
||||
public bool IsDisposed { get; private set; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~DisposableObject()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
public event EventHandler Disposing
|
||||
{
|
||||
add
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
_disposing += value;
|
||||
}
|
||||
remove
|
||||
{
|
||||
_disposing -= value;
|
||||
}
|
||||
}
|
||||
|
||||
protected void ThrowIfDisposed()
|
||||
{
|
||||
if (IsDisposed) throw new ObjectDisposedException(GetType().Name);
|
||||
}
|
||||
|
||||
protected void Dispose(bool disposing)
|
||||
{
|
||||
if (IsDisposed) return;
|
||||
|
||||
try
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_disposing?.Invoke(this, EventArgs.Empty);
|
||||
_disposing = null;
|
||||
DisposeManagedResources();
|
||||
}
|
||||
|
||||
DisposeNativeResources();
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsDisposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void DisposeManagedResources()
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void DisposeNativeResources()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using HandyControl.Controls;
|
||||
|
||||
namespace HandyControl.Data
|
||||
{
|
||||
internal class ChangeScope : DisposableObject
|
||||
{
|
||||
private readonly GlowWindow _window;
|
||||
|
||||
public ChangeScope(GlowWindow window)
|
||||
{
|
||||
_window = window;
|
||||
_window.DeferGlowChangesCount++;
|
||||
}
|
||||
|
||||
protected override void DisposeManagedResources()
|
||||
{
|
||||
_window.DeferGlowChangesCount--;
|
||||
if (_window.DeferGlowChangesCount == 0) _window.EndDeferGlowChanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using HandyControl.Tools.Interop;
|
||||
|
||||
namespace HandyControl.Data
|
||||
{
|
||||
internal class GlowBitmap : DisposableObject
|
||||
{
|
||||
internal const int GlowBitmapPartCount = 16;
|
||||
|
||||
private const int BytesPerPixelBgra32 = 4;
|
||||
|
||||
private static readonly CachedBitmapInfo[] _transparencyMasks = new CachedBitmapInfo[GlowBitmapPartCount];
|
||||
|
||||
private readonly InteropValues.BITMAPINFO _bitmapInfo;
|
||||
|
||||
private readonly IntPtr _pbits;
|
||||
|
||||
internal GlowBitmap(IntPtr hdcScreen, int width, int height)
|
||||
{
|
||||
_bitmapInfo.biSize = Marshal.SizeOf(typeof(InteropValues.BITMAPINFOHEADER));
|
||||
_bitmapInfo.biPlanes = 1;
|
||||
_bitmapInfo.biBitCount = 32;
|
||||
_bitmapInfo.biCompression = 0;
|
||||
_bitmapInfo.biXPelsPerMeter = 0;
|
||||
_bitmapInfo.biYPelsPerMeter = 0;
|
||||
_bitmapInfo.biWidth = width;
|
||||
_bitmapInfo.biHeight = -height;
|
||||
|
||||
Handle = InteropMethods.CreateDIBSection(
|
||||
hdcScreen,
|
||||
ref _bitmapInfo,
|
||||
0u,
|
||||
out _pbits,
|
||||
IntPtr.Zero,
|
||||
0u);
|
||||
}
|
||||
|
||||
internal IntPtr Handle { get; }
|
||||
|
||||
internal IntPtr DIBits => _pbits;
|
||||
|
||||
internal int Width => _bitmapInfo.biWidth;
|
||||
|
||||
internal int Height => -_bitmapInfo.biHeight;
|
||||
|
||||
protected override void DisposeNativeResources() => InteropMethods.DeleteObject(Handle);
|
||||
|
||||
private static byte PremultiplyAlpha(byte channel, byte alpha) => (byte)(channel * alpha / 255.0);
|
||||
|
||||
internal static GlowBitmap Create(GlowDrawingContext drawingContext, GlowBitmapPart bitmapPart, Color color)
|
||||
{
|
||||
var orCreateAlphaMask =
|
||||
GetOrCreateAlphaMask(bitmapPart);
|
||||
|
||||
var glowBitmap =
|
||||
new GlowBitmap(
|
||||
drawingContext.ScreenDC,
|
||||
orCreateAlphaMask.Width,
|
||||
orCreateAlphaMask.Height);
|
||||
|
||||
for (var i = 0; i < orCreateAlphaMask.DIBits.Length; i += BytesPerPixelBgra32)
|
||||
{
|
||||
var b = orCreateAlphaMask.DIBits[i + 3];
|
||||
var val = PremultiplyAlpha(color.R, b);
|
||||
var val2 = PremultiplyAlpha(color.G, b);
|
||||
var val3 = PremultiplyAlpha(color.B, b);
|
||||
Marshal.WriteByte(glowBitmap.DIBits, i, val3);
|
||||
Marshal.WriteByte(glowBitmap.DIBits, i + 1, val2);
|
||||
Marshal.WriteByte(glowBitmap.DIBits, i + 2, val);
|
||||
Marshal.WriteByte(glowBitmap.DIBits, i + 3, b);
|
||||
}
|
||||
|
||||
return glowBitmap;
|
||||
}
|
||||
|
||||
private static CachedBitmapInfo GetOrCreateAlphaMask(GlowBitmapPart bitmapPart)
|
||||
{
|
||||
if (_transparencyMasks[(int)bitmapPart] == null)
|
||||
{
|
||||
var bitmapImage = new BitmapImage(new Uri($"pack://application:,,,/HandyControl;Component/Resources/Images/GlowWindow/{bitmapPart}.png"));
|
||||
|
||||
var array = new byte[BytesPerPixelBgra32 * bitmapImage.PixelWidth * bitmapImage.PixelHeight];
|
||||
var stride = BytesPerPixelBgra32 * bitmapImage.PixelWidth;
|
||||
bitmapImage.CopyPixels(array, stride, 0);
|
||||
|
||||
_transparencyMasks[(int)bitmapPart] =
|
||||
new CachedBitmapInfo(
|
||||
array,
|
||||
bitmapImage.PixelWidth,
|
||||
bitmapImage.PixelHeight);
|
||||
}
|
||||
|
||||
return _transparencyMasks[(int)bitmapPart];
|
||||
}
|
||||
|
||||
private sealed class CachedBitmapInfo
|
||||
{
|
||||
internal readonly byte[] DIBits;
|
||||
internal readonly int Height;
|
||||
internal readonly int Width;
|
||||
|
||||
internal CachedBitmapInfo(byte[] diBits, int width, int height)
|
||||
{
|
||||
Width = width;
|
||||
Height = height;
|
||||
DIBits = diBits;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace HandyControl.Data
|
||||
{
|
||||
internal enum GlowBitmapPart
|
||||
{
|
||||
CornerTopLeft,
|
||||
CornerTopRight,
|
||||
CornerBottomLeft,
|
||||
CornerBottomRight,
|
||||
TopLeft,
|
||||
Top,
|
||||
TopRight,
|
||||
LeftTop,
|
||||
Left,
|
||||
LeftBottom,
|
||||
BottomLeft,
|
||||
Bottom,
|
||||
BottomRight,
|
||||
RightTop,
|
||||
Right,
|
||||
RightBottom
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using HandyControl.Tools.Interop;
|
||||
|
||||
namespace HandyControl.Data
|
||||
{
|
||||
internal class GlowDrawingContext : DisposableObject
|
||||
{
|
||||
private readonly GlowBitmap _windowBitmap;
|
||||
|
||||
internal InteropValues.BLENDFUNCTION Blend;
|
||||
|
||||
internal GlowDrawingContext(int width, int height)
|
||||
{
|
||||
ScreenDC = InteropMethods.GetDC(IntPtr.Zero);
|
||||
if (ScreenDC == IntPtr.Zero) return;
|
||||
WindowDC = InteropMethods.CreateCompatibleDC(ScreenDC);
|
||||
if (WindowDC == IntPtr.Zero) return;
|
||||
BackgroundDC = InteropMethods.CreateCompatibleDC(ScreenDC);
|
||||
if (BackgroundDC == IntPtr.Zero) return;
|
||||
Blend.BlendOp = 0;
|
||||
Blend.BlendFlags = 0;
|
||||
Blend.SourceConstantAlpha = 255;
|
||||
Blend.AlphaFormat = 1;
|
||||
_windowBitmap = new GlowBitmap(ScreenDC, width, height);
|
||||
InteropMethods.SelectObject(WindowDC, _windowBitmap.Handle);
|
||||
}
|
||||
|
||||
internal bool IsInitialized =>
|
||||
ScreenDC != IntPtr.Zero && WindowDC != IntPtr.Zero &&
|
||||
BackgroundDC != IntPtr.Zero && _windowBitmap != null;
|
||||
|
||||
internal IntPtr ScreenDC { get; }
|
||||
|
||||
internal IntPtr WindowDC { get; }
|
||||
|
||||
internal IntPtr BackgroundDC { get; }
|
||||
|
||||
internal int Width => _windowBitmap.Width;
|
||||
|
||||
internal int Height => _windowBitmap.Height;
|
||||
|
||||
protected override void DisposeManagedResources() => _windowBitmap.Dispose();
|
||||
|
||||
protected override void DisposeNativeResources()
|
||||
{
|
||||
if (ScreenDC != IntPtr.Zero) InteropMethods.ReleaseDC(IntPtr.Zero, ScreenDC);
|
||||
if (WindowDC != IntPtr.Zero) InteropMethods.DeleteDC(WindowDC);
|
||||
if (BackgroundDC != IntPtr.Zero) InteropMethods.DeleteDC(BackgroundDC);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,587 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Media;
|
||||
using HandyControl.Controls;
|
||||
using HandyControl.Tools.Interop;
|
||||
|
||||
namespace HandyControl.Data
|
||||
{
|
||||
internal class GlowEdge : HwndWrapper
|
||||
{
|
||||
private const string GlowEdgeClassName = "HandyControlGlowEdge";
|
||||
|
||||
private const int GlowDepth = 9;
|
||||
|
||||
private const int CornerGripThickness = 18;
|
||||
|
||||
private static ushort _sharedWindowClassAtom;
|
||||
|
||||
// ReSharper disable once NotAccessedField.Local
|
||||
private static InteropValues.WndProc _sharedWndProc;
|
||||
|
||||
private readonly GlowBitmap[] _activeGlowBitmaps = new GlowBitmap[16];
|
||||
|
||||
private readonly GlowBitmap[] _inactiveGlowBitmaps = new GlowBitmap[16];
|
||||
|
||||
private readonly Dock _orientation;
|
||||
|
||||
private readonly GlowWindow _targetWindow;
|
||||
|
||||
private Color _activeGlowColor = Colors.Transparent;
|
||||
|
||||
private int _height;
|
||||
|
||||
private Color _inactiveGlowColor = Colors.Transparent;
|
||||
|
||||
private FieldInvalidationTypes _invalidatedValues;
|
||||
|
||||
private bool _isActive;
|
||||
|
||||
private bool _isVisible;
|
||||
|
||||
private int _left;
|
||||
|
||||
private bool _pendingDelayRender;
|
||||
|
||||
private int _top;
|
||||
|
||||
private int _width;
|
||||
|
||||
internal static long CreatedGlowEdges { get; private set; }
|
||||
|
||||
internal static long DisposedGlowEdges { get; private set; }
|
||||
|
||||
internal GlowEdge(GlowWindow owner, Dock orientation)
|
||||
{
|
||||
_targetWindow = owner ?? throw new ArgumentNullException(nameof(owner));
|
||||
_orientation = orientation;
|
||||
CreatedGlowEdges += 1L;
|
||||
}
|
||||
|
||||
private bool IsDeferringChanges => _targetWindow.DeferGlowChangesCount > 0;
|
||||
|
||||
private static ushort SharedWindowClassAtom
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_sharedWindowClassAtom == 0)
|
||||
{
|
||||
var wndclass = default(InteropValues.WNDCLASS);
|
||||
|
||||
wndclass.cbClsExtra = 0;
|
||||
wndclass.cbWndExtra = 0;
|
||||
wndclass.hbrBackground = IntPtr.Zero;
|
||||
wndclass.hCursor = IntPtr.Zero;
|
||||
wndclass.hIcon = IntPtr.Zero;
|
||||
wndclass.lpfnWndProc = _sharedWndProc = InteropMethods.DefWindowProc;
|
||||
wndclass.lpszClassName = GlowEdgeClassName;
|
||||
wndclass.lpszMenuName = null;
|
||||
wndclass.style = 0u;
|
||||
|
||||
_sharedWindowClassAtom = InteropMethods.RegisterClass(ref wndclass);
|
||||
}
|
||||
|
||||
return _sharedWindowClassAtom;
|
||||
}
|
||||
}
|
||||
|
||||
internal bool IsVisible
|
||||
{
|
||||
get => _isVisible;
|
||||
set => UpdateProperty(ref _isVisible, value, FieldInvalidationTypes.Render | FieldInvalidationTypes.Visibility);
|
||||
}
|
||||
|
||||
internal int Left
|
||||
{
|
||||
get => _left;
|
||||
set => UpdateProperty(ref _left, value, FieldInvalidationTypes.Location);
|
||||
}
|
||||
|
||||
internal int Top
|
||||
{
|
||||
get => _top;
|
||||
set => UpdateProperty(ref _top, value, FieldInvalidationTypes.Location);
|
||||
}
|
||||
|
||||
internal int Width
|
||||
{
|
||||
get => _width;
|
||||
set => UpdateProperty( ref _width, value, FieldInvalidationTypes.Size | FieldInvalidationTypes.Render);
|
||||
}
|
||||
|
||||
internal int Height
|
||||
{
|
||||
get => _height;
|
||||
set => UpdateProperty(ref _height, value, FieldInvalidationTypes.Size | FieldInvalidationTypes.Render);
|
||||
}
|
||||
|
||||
internal bool IsActive
|
||||
{
|
||||
get => _isActive;
|
||||
set => UpdateProperty(ref _isActive, value, FieldInvalidationTypes.Render);
|
||||
}
|
||||
|
||||
internal Color ActiveGlowColor
|
||||
{
|
||||
get => _activeGlowColor;
|
||||
set => UpdateProperty(ref _activeGlowColor, value, FieldInvalidationTypes.ActiveColor | FieldInvalidationTypes.Render);
|
||||
}
|
||||
|
||||
internal Color InactiveGlowColor
|
||||
{
|
||||
get => _inactiveGlowColor;
|
||||
set => UpdateProperty(ref _inactiveGlowColor, value, FieldInvalidationTypes.InactiveColor | FieldInvalidationTypes.Render);
|
||||
}
|
||||
|
||||
private IntPtr TargetWindowHandle => new WindowInteropHelper(_targetWindow).Handle;
|
||||
|
||||
protected override bool IsWindowSubclassed => true;
|
||||
|
||||
private bool IsPositionValid => (_invalidatedValues & (FieldInvalidationTypes.Location | FieldInvalidationTypes.Size | FieldInvalidationTypes.Visibility)) == FieldInvalidationTypes.None;
|
||||
|
||||
private void UpdateProperty<T>(ref T field, T value, FieldInvalidationTypes invalidatedValues) where T : struct
|
||||
{
|
||||
if (!field.Equals(value))
|
||||
{
|
||||
field = value;
|
||||
_invalidatedValues |= invalidatedValues;
|
||||
if (!IsDeferringChanges) CommitChanges();
|
||||
}
|
||||
}
|
||||
|
||||
protected override ushort CreateWindowClassCore() => SharedWindowClassAtom;
|
||||
|
||||
protected override void DestroyWindowClassCore()
|
||||
{
|
||||
}
|
||||
|
||||
protected override IntPtr CreateWindowCore()
|
||||
{
|
||||
return InteropMethods.CreateWindowEx(
|
||||
524416,
|
||||
new IntPtr(WindowClassAtom),
|
||||
string.Empty,
|
||||
-2046820352,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
new WindowInteropHelper(_targetWindow).Owner,
|
||||
IntPtr.Zero,
|
||||
IntPtr.Zero,
|
||||
IntPtr.Zero);
|
||||
}
|
||||
|
||||
internal void ChangeOwner(IntPtr newOwner) => InteropMethods.SetWindowLongPtr(Handle, InteropValues.GWLP.HWNDPARENT, newOwner);
|
||||
|
||||
protected override IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
if (msg <= 70)
|
||||
{
|
||||
if (msg == 6) return IntPtr.Zero;
|
||||
if (msg == 70)
|
||||
{
|
||||
var windowpos = (InteropValues.WINDOWPOS)Marshal.PtrToStructure(lParam, typeof(InteropValues.WINDOWPOS));
|
||||
windowpos.flags |= 16u;
|
||||
Marshal.StructureToPtr(windowpos, lParam, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (msg != 126)
|
||||
{
|
||||
if (msg == 132) return new IntPtr(WmNcHitTest(lParam));
|
||||
switch (msg)
|
||||
{
|
||||
case 161:
|
||||
case 163:
|
||||
case 164:
|
||||
case 166:
|
||||
case 167:
|
||||
case 169:
|
||||
case 171:
|
||||
case 173:
|
||||
{
|
||||
var targetWindowHandle = TargetWindowHandle;
|
||||
InteropMethods.SendMessage(targetWindowHandle, 6, new IntPtr(2), IntPtr.Zero);
|
||||
InteropMethods.SendMessage(targetWindowHandle, msg, wParam, IntPtr.Zero);
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IsVisible) RenderLayeredWindow();
|
||||
}
|
||||
}
|
||||
|
||||
return base.WndProc(hwnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
private int WmNcHitTest(IntPtr lParam)
|
||||
{
|
||||
var xLParam = InteropMethods.GetXLParam(lParam.ToInt32());
|
||||
var yLParam = InteropMethods.GetYLParam(lParam.ToInt32());
|
||||
InteropMethods.GetWindowRect(Handle, out var rect);
|
||||
switch (_orientation)
|
||||
{
|
||||
case Dock.Left:
|
||||
if (yLParam - CornerGripThickness < rect.Top) return 13;
|
||||
if (yLParam + CornerGripThickness > rect.Bottom) return 16;
|
||||
return 10;
|
||||
case Dock.Top:
|
||||
if (xLParam - CornerGripThickness < rect.Left) return 13;
|
||||
if (xLParam + CornerGripThickness > rect.Right) return 14;
|
||||
return 12;
|
||||
case Dock.Right:
|
||||
if (yLParam - CornerGripThickness < rect.Top) return 14;
|
||||
if (yLParam + CornerGripThickness > rect.Bottom) return 17;
|
||||
return 11;
|
||||
default:
|
||||
if (xLParam - CornerGripThickness < rect.Left) return 16;
|
||||
if (xLParam + CornerGripThickness > rect.Right) return 17;
|
||||
return 15;
|
||||
}
|
||||
}
|
||||
|
||||
internal void CommitChanges()
|
||||
{
|
||||
InvalidateCachedBitmaps();
|
||||
UpdateWindowPosCore();
|
||||
UpdateLayeredWindowCore();
|
||||
_invalidatedValues = FieldInvalidationTypes.None;
|
||||
}
|
||||
|
||||
private void InvalidateCachedBitmaps()
|
||||
{
|
||||
if (_invalidatedValues.HasFlag(FieldInvalidationTypes.ActiveColor)) ClearCache(_activeGlowBitmaps);
|
||||
if (_invalidatedValues.HasFlag(FieldInvalidationTypes.InactiveColor)) ClearCache(_inactiveGlowBitmaps);
|
||||
}
|
||||
|
||||
private void UpdateWindowPosCore()
|
||||
{
|
||||
if (_invalidatedValues.HasFlag(FieldInvalidationTypes.Location) ||
|
||||
_invalidatedValues.HasFlag(FieldInvalidationTypes.Size) ||
|
||||
_invalidatedValues.HasFlag(FieldInvalidationTypes.Visibility))
|
||||
{
|
||||
var num = 532;
|
||||
if (_invalidatedValues.HasFlag(FieldInvalidationTypes.Visibility))
|
||||
{
|
||||
if (IsVisible)
|
||||
num |= 64;
|
||||
else
|
||||
num |= 131;
|
||||
}
|
||||
|
||||
if (!_invalidatedValues.HasFlag(FieldInvalidationTypes.Location)) num |= 2;
|
||||
if (!_invalidatedValues.HasFlag(FieldInvalidationTypes.Size)) num |= 1;
|
||||
InteropMethods.SetWindowPos(Handle, IntPtr.Zero, Left, Top, Width, Height, num);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateLayeredWindowCore()
|
||||
{
|
||||
if (IsVisible && _invalidatedValues.HasFlag(FieldInvalidationTypes.Render))
|
||||
{
|
||||
if (IsPositionValid)
|
||||
{
|
||||
BeginDelayedRender();
|
||||
return;
|
||||
}
|
||||
|
||||
CancelDelayedRender();
|
||||
RenderLayeredWindow();
|
||||
}
|
||||
}
|
||||
|
||||
private void BeginDelayedRender()
|
||||
{
|
||||
if (!_pendingDelayRender)
|
||||
{
|
||||
_pendingDelayRender = true;
|
||||
CompositionTarget.Rendering += CommitDelayedRender;
|
||||
}
|
||||
}
|
||||
|
||||
private void CancelDelayedRender()
|
||||
{
|
||||
if (_pendingDelayRender)
|
||||
{
|
||||
_pendingDelayRender = false;
|
||||
CompositionTarget.Rendering -= CommitDelayedRender;
|
||||
}
|
||||
}
|
||||
|
||||
private void CommitDelayedRender(object sender, EventArgs e)
|
||||
{
|
||||
CancelDelayedRender();
|
||||
if (IsVisible) RenderLayeredWindow();
|
||||
}
|
||||
|
||||
private void RenderLayeredWindow()
|
||||
{
|
||||
using var glowDrawingContext = new GlowDrawingContext(Width, Height);
|
||||
if (glowDrawingContext.IsInitialized)
|
||||
{
|
||||
switch (_orientation)
|
||||
{
|
||||
case Dock.Left:
|
||||
DrawLeft(glowDrawingContext);
|
||||
break;
|
||||
case Dock.Top:
|
||||
DrawTop(glowDrawingContext);
|
||||
break;
|
||||
case Dock.Right:
|
||||
DrawRight(glowDrawingContext);
|
||||
break;
|
||||
default:
|
||||
DrawBottom(glowDrawingContext);
|
||||
break;
|
||||
}
|
||||
|
||||
var point = new InteropValues.POINT
|
||||
{
|
||||
X = Left,
|
||||
Y = Top
|
||||
};
|
||||
var size = new InteropValues.SIZE
|
||||
{
|
||||
cx = Width,
|
||||
cy = Height
|
||||
};
|
||||
var point2 = new InteropValues.POINT
|
||||
{
|
||||
X = 0,
|
||||
Y = 0
|
||||
};
|
||||
|
||||
InteropMethods.UpdateLayeredWindow(
|
||||
Handle,
|
||||
glowDrawingContext.ScreenDC,
|
||||
ref point,
|
||||
ref size,
|
||||
glowDrawingContext.WindowDC,
|
||||
ref point2,
|
||||
0u,
|
||||
ref glowDrawingContext.Blend,
|
||||
2u);
|
||||
}
|
||||
}
|
||||
|
||||
private GlowBitmap GetOrCreateBitmap(GlowDrawingContext drawingContext, GlowBitmapPart bitmapPart)
|
||||
{
|
||||
GlowBitmap[] array;
|
||||
Color color;
|
||||
if (IsActive)
|
||||
{
|
||||
array = _activeGlowBitmaps;
|
||||
color = ActiveGlowColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
array = _inactiveGlowBitmaps;
|
||||
color = InactiveGlowColor;
|
||||
}
|
||||
|
||||
return array[(int) bitmapPart] ?? (array[(int) bitmapPart] = GlowBitmap.Create(drawingContext, bitmapPart, color));
|
||||
}
|
||||
|
||||
private void ClearCache(GlowBitmap[] cache)
|
||||
{
|
||||
for (var i = 0; i < cache.Length; i++)
|
||||
using (cache[i])
|
||||
{
|
||||
cache[i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void DisposeManagedResources()
|
||||
{
|
||||
ClearCache(_activeGlowBitmaps);
|
||||
ClearCache(_inactiveGlowBitmaps);
|
||||
}
|
||||
|
||||
protected override void DisposeNativeResources()
|
||||
{
|
||||
base.DisposeNativeResources();
|
||||
DisposedGlowEdges += 1L;
|
||||
}
|
||||
|
||||
private void DrawLeft(GlowDrawingContext drawingContext)
|
||||
{
|
||||
var orCreateBitmap = GetOrCreateBitmap(drawingContext, GlowBitmapPart.CornerTopLeft);
|
||||
var orCreateBitmap2 = GetOrCreateBitmap(drawingContext, GlowBitmapPart.LeftTop);
|
||||
var orCreateBitmap3 = GetOrCreateBitmap(drawingContext, GlowBitmapPart.Left);
|
||||
var orCreateBitmap4 = GetOrCreateBitmap(drawingContext, GlowBitmapPart.LeftBottom);
|
||||
var orCreateBitmap5 = GetOrCreateBitmap(drawingContext, GlowBitmapPart.CornerBottomLeft);
|
||||
var height = orCreateBitmap.Height;
|
||||
var num = height + orCreateBitmap2.Height;
|
||||
var num2 = drawingContext.Height - orCreateBitmap5.Height;
|
||||
var num3 = num2 - orCreateBitmap4.Height;
|
||||
var num4 = num3 - num;
|
||||
InteropMethods.SelectObject(drawingContext.BackgroundDC, orCreateBitmap.Handle);
|
||||
InteropMethods.AlphaBlend(drawingContext.WindowDC, 0, 0, orCreateBitmap.Width, orCreateBitmap.Height,
|
||||
drawingContext.BackgroundDC, 0, 0, orCreateBitmap.Width, orCreateBitmap.Height,
|
||||
drawingContext.Blend);
|
||||
InteropMethods.SelectObject(drawingContext.BackgroundDC, orCreateBitmap2.Handle);
|
||||
InteropMethods.AlphaBlend(drawingContext.WindowDC, 0, height, orCreateBitmap2.Width,
|
||||
orCreateBitmap2.Height, drawingContext.BackgroundDC, 0, 0, orCreateBitmap2.Width,
|
||||
orCreateBitmap2.Height, drawingContext.Blend);
|
||||
if (num4 > 0)
|
||||
{
|
||||
InteropMethods.SelectObject(drawingContext.BackgroundDC, orCreateBitmap3.Handle);
|
||||
InteropMethods.AlphaBlend(drawingContext.WindowDC, 0, num, orCreateBitmap3.Width, num4,
|
||||
drawingContext.BackgroundDC, 0, 0, orCreateBitmap3.Width, orCreateBitmap3.Height,
|
||||
drawingContext.Blend);
|
||||
}
|
||||
|
||||
InteropMethods.SelectObject(drawingContext.BackgroundDC, orCreateBitmap4.Handle);
|
||||
InteropMethods.AlphaBlend(drawingContext.WindowDC, 0, num3, orCreateBitmap4.Width,
|
||||
orCreateBitmap4.Height, drawingContext.BackgroundDC, 0, 0, orCreateBitmap4.Width,
|
||||
orCreateBitmap4.Height, drawingContext.Blend);
|
||||
InteropMethods.SelectObject(drawingContext.BackgroundDC, orCreateBitmap5.Handle);
|
||||
InteropMethods.AlphaBlend(drawingContext.WindowDC, 0, num2, orCreateBitmap5.Width,
|
||||
orCreateBitmap5.Height, drawingContext.BackgroundDC, 0, 0, orCreateBitmap5.Width,
|
||||
orCreateBitmap5.Height, drawingContext.Blend);
|
||||
}
|
||||
|
||||
private void DrawRight(GlowDrawingContext drawingContext)
|
||||
{
|
||||
var orCreateBitmap = GetOrCreateBitmap(drawingContext, GlowBitmapPart.CornerTopRight);
|
||||
var orCreateBitmap2 = GetOrCreateBitmap(drawingContext, GlowBitmapPart.RightTop);
|
||||
var orCreateBitmap3 = GetOrCreateBitmap(drawingContext, GlowBitmapPart.Right);
|
||||
var orCreateBitmap4 = GetOrCreateBitmap(drawingContext, GlowBitmapPart.RightBottom);
|
||||
var orCreateBitmap5 = GetOrCreateBitmap(drawingContext, GlowBitmapPart.CornerBottomRight);
|
||||
var height = orCreateBitmap.Height;
|
||||
var num = height + orCreateBitmap2.Height;
|
||||
var num2 = drawingContext.Height - orCreateBitmap5.Height;
|
||||
var num3 = num2 - orCreateBitmap4.Height;
|
||||
var num4 = num3 - num;
|
||||
InteropMethods.SelectObject(drawingContext.BackgroundDC, orCreateBitmap.Handle);
|
||||
InteropMethods.AlphaBlend(drawingContext.WindowDC, 0, 0, orCreateBitmap.Width, orCreateBitmap.Height,
|
||||
drawingContext.BackgroundDC, 0, 0, orCreateBitmap.Width, orCreateBitmap.Height,
|
||||
drawingContext.Blend);
|
||||
InteropMethods.SelectObject(drawingContext.BackgroundDC, orCreateBitmap2.Handle);
|
||||
InteropMethods.AlphaBlend(drawingContext.WindowDC, 0, height, orCreateBitmap2.Width,
|
||||
orCreateBitmap2.Height, drawingContext.BackgroundDC, 0, 0, orCreateBitmap2.Width,
|
||||
orCreateBitmap2.Height, drawingContext.Blend);
|
||||
if (num4 > 0)
|
||||
{
|
||||
InteropMethods.SelectObject(drawingContext.BackgroundDC, orCreateBitmap3.Handle);
|
||||
InteropMethods.AlphaBlend(drawingContext.WindowDC, 0, num, orCreateBitmap3.Width, num4,
|
||||
drawingContext.BackgroundDC, 0, 0, orCreateBitmap3.Width, orCreateBitmap3.Height,
|
||||
drawingContext.Blend);
|
||||
}
|
||||
|
||||
InteropMethods.SelectObject(drawingContext.BackgroundDC, orCreateBitmap4.Handle);
|
||||
InteropMethods.AlphaBlend(drawingContext.WindowDC, 0, num3, orCreateBitmap4.Width,
|
||||
orCreateBitmap4.Height, drawingContext.BackgroundDC, 0, 0, orCreateBitmap4.Width,
|
||||
orCreateBitmap4.Height, drawingContext.Blend);
|
||||
InteropMethods.SelectObject(drawingContext.BackgroundDC, orCreateBitmap5.Handle);
|
||||
InteropMethods.AlphaBlend(drawingContext.WindowDC, 0, num2, orCreateBitmap5.Width,
|
||||
orCreateBitmap5.Height, drawingContext.BackgroundDC, 0, 0, orCreateBitmap5.Width,
|
||||
orCreateBitmap5.Height, drawingContext.Blend);
|
||||
}
|
||||
|
||||
private void DrawTop(GlowDrawingContext drawingContext)
|
||||
{
|
||||
var orCreateBitmap = GetOrCreateBitmap(drawingContext, GlowBitmapPart.TopLeft);
|
||||
var orCreateBitmap2 = GetOrCreateBitmap(drawingContext, GlowBitmapPart.Top);
|
||||
var orCreateBitmap3 = GetOrCreateBitmap(drawingContext, GlowBitmapPart.TopRight);
|
||||
var num2 = GlowDepth + orCreateBitmap.Width;
|
||||
var num3 = drawingContext.Width - GlowDepth - orCreateBitmap3.Width;
|
||||
var num4 = num3 - num2;
|
||||
InteropMethods.SelectObject(drawingContext.BackgroundDC, orCreateBitmap.Handle);
|
||||
InteropMethods.AlphaBlend(drawingContext.WindowDC, GlowDepth, 0, orCreateBitmap.Width, orCreateBitmap.Height,
|
||||
drawingContext.BackgroundDC, 0, 0, orCreateBitmap.Width, orCreateBitmap.Height,
|
||||
drawingContext.Blend);
|
||||
if (num4 > 0)
|
||||
{
|
||||
InteropMethods.SelectObject(drawingContext.BackgroundDC, orCreateBitmap2.Handle);
|
||||
InteropMethods.AlphaBlend(drawingContext.WindowDC, num2, 0, num4, orCreateBitmap2.Height,
|
||||
drawingContext.BackgroundDC, 0, 0, orCreateBitmap2.Width, orCreateBitmap2.Height,
|
||||
drawingContext.Blend);
|
||||
}
|
||||
|
||||
InteropMethods.SelectObject(drawingContext.BackgroundDC, orCreateBitmap3.Handle);
|
||||
InteropMethods.AlphaBlend(drawingContext.WindowDC, num3, 0, orCreateBitmap3.Width,
|
||||
orCreateBitmap3.Height, drawingContext.BackgroundDC, 0, 0, orCreateBitmap3.Width,
|
||||
orCreateBitmap3.Height, drawingContext.Blend);
|
||||
}
|
||||
|
||||
private void DrawBottom(GlowDrawingContext drawingContext)
|
||||
{
|
||||
var orCreateBitmap = GetOrCreateBitmap(drawingContext, GlowBitmapPart.BottomLeft);
|
||||
var orCreateBitmap2 = GetOrCreateBitmap(drawingContext, GlowBitmapPart.Bottom);
|
||||
var orCreateBitmap3 = GetOrCreateBitmap(drawingContext, GlowBitmapPart.BottomRight);
|
||||
var num2 = GlowDepth + orCreateBitmap.Width;
|
||||
var num3 = drawingContext.Width - GlowDepth - orCreateBitmap3.Width;
|
||||
var num4 = num3 - num2;
|
||||
InteropMethods.SelectObject(drawingContext.BackgroundDC, orCreateBitmap.Handle);
|
||||
InteropMethods.AlphaBlend(drawingContext.WindowDC, GlowDepth, 0, orCreateBitmap.Width, orCreateBitmap.Height,
|
||||
drawingContext.BackgroundDC, 0, 0, orCreateBitmap.Width, orCreateBitmap.Height,
|
||||
drawingContext.Blend);
|
||||
if (num4 > 0)
|
||||
{
|
||||
InteropMethods.SelectObject(drawingContext.BackgroundDC, orCreateBitmap2.Handle);
|
||||
InteropMethods.AlphaBlend(drawingContext.WindowDC, num2, 0, num4, orCreateBitmap2.Height,
|
||||
drawingContext.BackgroundDC, 0, 0, orCreateBitmap2.Width, orCreateBitmap2.Height,
|
||||
drawingContext.Blend);
|
||||
}
|
||||
|
||||
InteropMethods.SelectObject(drawingContext.BackgroundDC, orCreateBitmap3.Handle);
|
||||
InteropMethods.AlphaBlend(drawingContext.WindowDC, num3, 0, orCreateBitmap3.Width,
|
||||
orCreateBitmap3.Height, drawingContext.BackgroundDC, 0, 0, orCreateBitmap3.Width,
|
||||
orCreateBitmap3.Height, drawingContext.Blend);
|
||||
}
|
||||
|
||||
internal void UpdateWindowPos()
|
||||
{
|
||||
var targetWindowHandle = TargetWindowHandle;
|
||||
InteropMethods.GetWindowRect(targetWindowHandle, out var rect);
|
||||
InteropMethods.GetWindowPlacement(targetWindowHandle);
|
||||
if (IsVisible)
|
||||
switch (_orientation)
|
||||
{
|
||||
case Dock.Left:
|
||||
Left = rect.Left - GlowDepth;
|
||||
Top = rect.Top - GlowDepth;
|
||||
Width = GlowDepth;
|
||||
Height = rect.Height + CornerGripThickness;
|
||||
return;
|
||||
case Dock.Top:
|
||||
Left = rect.Left - GlowDepth;
|
||||
Top = rect.Top - GlowDepth;
|
||||
Width = rect.Width + CornerGripThickness;
|
||||
Height = GlowDepth;
|
||||
return;
|
||||
case Dock.Right:
|
||||
Left = rect.Right;
|
||||
Top = rect.Top - GlowDepth;
|
||||
Width = GlowDepth;
|
||||
Height = rect.Height + CornerGripThickness;
|
||||
return;
|
||||
default:
|
||||
Left = rect.Left - GlowDepth;
|
||||
Top = rect.Bottom;
|
||||
Width = rect.Width + CornerGripThickness;
|
||||
Height = GlowDepth;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
[Flags]
|
||||
private enum FieldInvalidationTypes
|
||||
{
|
||||
None = 0,
|
||||
Location = 1,
|
||||
Size = 2,
|
||||
ActiveColor = 4,
|
||||
InactiveColor = 8,
|
||||
Render = 16,
|
||||
Visibility = 32
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using HandyControl.Tools.Interop;
|
||||
|
||||
namespace HandyControl.Data
|
||||
{
|
||||
public abstract class HwndWrapper : DisposableObject
|
||||
{
|
||||
private IntPtr _handle;
|
||||
|
||||
private bool _isHandleCreationAllowed = true;
|
||||
|
||||
private ushort _wndClassAtom;
|
||||
|
||||
private Delegate _wndProc;
|
||||
|
||||
protected ushort WindowClassAtom
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_wndClassAtom == 0) _wndClassAtom = CreateWindowClassCore();
|
||||
return _wndClassAtom;
|
||||
}
|
||||
}
|
||||
|
||||
public IntPtr Handle
|
||||
{
|
||||
get
|
||||
{
|
||||
EnsureHandle();
|
||||
return _handle;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual bool IsWindowSubclassed => false;
|
||||
|
||||
protected virtual ushort CreateWindowClassCore() => RegisterClass(Guid.NewGuid().ToString());
|
||||
|
||||
protected virtual void DestroyWindowClassCore()
|
||||
{
|
||||
if (_wndClassAtom != 0)
|
||||
{
|
||||
var moduleHandle = InteropMethods.GetModuleHandle(null);
|
||||
InteropMethods.UnregisterClass(new IntPtr(_wndClassAtom), moduleHandle);
|
||||
_wndClassAtom = 0;
|
||||
}
|
||||
}
|
||||
|
||||
protected ushort RegisterClass(string className)
|
||||
{
|
||||
var wndClass = default(InteropValues.WNDCLASS);
|
||||
wndClass.cbClsExtra = 0;
|
||||
wndClass.cbWndExtra = 0;
|
||||
wndClass.hbrBackground = IntPtr.Zero;
|
||||
wndClass.hCursor = IntPtr.Zero;
|
||||
wndClass.hIcon = IntPtr.Zero;
|
||||
wndClass.lpfnWndProc = _wndProc = new InteropValues.WndProc(WndProc);
|
||||
wndClass.lpszClassName = className;
|
||||
wndClass.lpszMenuName = null;
|
||||
wndClass.style = 0u;
|
||||
return InteropMethods.RegisterClass(ref wndClass);
|
||||
}
|
||||
|
||||
private void SubclassWndProc()
|
||||
{
|
||||
_wndProc = new InteropValues.WndProc(WndProc);
|
||||
InteropMethods.SetWindowLong(_handle, -4, Marshal.GetFunctionPointerForDelegate(_wndProc));
|
||||
}
|
||||
|
||||
protected abstract IntPtr CreateWindowCore();
|
||||
|
||||
protected virtual void DestroyWindowCore()
|
||||
{
|
||||
if (_handle != IntPtr.Zero)
|
||||
{
|
||||
InteropMethods.DestroyWindow(_handle);
|
||||
_handle = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam) =>
|
||||
InteropMethods.DefWindowProc(hwnd, msg, wParam, lParam);
|
||||
|
||||
public void EnsureHandle()
|
||||
{
|
||||
if (_handle == IntPtr.Zero)
|
||||
{
|
||||
if (!_isHandleCreationAllowed) return;
|
||||
_isHandleCreationAllowed = false;
|
||||
_handle = CreateWindowCore();
|
||||
if (IsWindowSubclassed) SubclassWndProc();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void DisposeNativeResources()
|
||||
{
|
||||
_isHandleCreationAllowed = false;
|
||||
DestroyWindowCore();
|
||||
DestroyWindowClassCore();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -302,6 +302,10 @@
|
||||
|
||||
internal const string WindowWin10 = nameof(WindowWin10);
|
||||
|
||||
internal const string WindowBlur = nameof(WindowBlur);
|
||||
|
||||
internal const string WindowGlow = nameof(WindowGlow);
|
||||
|
||||
internal const string AddTagButtonStyle = nameof(AddTagButtonStyle);
|
||||
|
||||
internal const string RadioGroupItemDefault = nameof(RadioGroupItemDefault);
|
||||
|
||||
Reference in new issue
Block a user