Files
HandyControl/src/Shared/HandyControl_Shared/Data/HwndWrapper.cs
T
2020-01-18 14:23:47 +08:00

102 lines
3.0 KiB
C#

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();
}
}
}