102 lines
3.0 KiB
C#
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();
|
|
}
|
|
}
|
|
} |