HwndWrapper.cs 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. using System;
  2. using System.Runtime.InteropServices;
  3. using HandyControl.Tools.Interop;
  4. namespace HandyControl.Data;
  5. public abstract class HwndWrapper : DisposableObject
  6. {
  7. private IntPtr _handle;
  8. private bool _isHandleCreationAllowed = true;
  9. private ushort _wndClassAtom;
  10. private Delegate _wndProc;
  11. protected ushort WindowClassAtom
  12. {
  13. get
  14. {
  15. if (_wndClassAtom == 0) _wndClassAtom = CreateWindowClassCore();
  16. return _wndClassAtom;
  17. }
  18. }
  19. public IntPtr Handle
  20. {
  21. get
  22. {
  23. EnsureHandle();
  24. return _handle;
  25. }
  26. }
  27. protected virtual bool IsWindowSubclassed => false;
  28. protected virtual ushort CreateWindowClassCore() => RegisterClass(Guid.NewGuid().ToString());
  29. protected virtual void DestroyWindowClassCore()
  30. {
  31. if (_wndClassAtom != 0)
  32. {
  33. var moduleHandle = InteropMethods.GetModuleHandle(null);
  34. InteropMethods.UnregisterClass(new IntPtr(_wndClassAtom), moduleHandle);
  35. _wndClassAtom = 0;
  36. }
  37. }
  38. protected ushort RegisterClass(string className)
  39. {
  40. var wndClass = default(InteropValues.WNDCLASS);
  41. wndClass.cbClsExtra = 0;
  42. wndClass.cbWndExtra = 0;
  43. wndClass.hbrBackground = IntPtr.Zero;
  44. wndClass.hCursor = IntPtr.Zero;
  45. wndClass.hIcon = IntPtr.Zero;
  46. wndClass.lpfnWndProc = _wndProc = new InteropValues.WndProc(WndProc);
  47. wndClass.lpszClassName = className;
  48. wndClass.lpszMenuName = null;
  49. wndClass.style = 0u;
  50. return InteropMethods.RegisterClass(ref wndClass);
  51. }
  52. private void SubclassWndProc()
  53. {
  54. _wndProc = new InteropValues.WndProc(WndProc);
  55. InteropMethods.SetWindowLong(_handle, -4, Marshal.GetFunctionPointerForDelegate(_wndProc));
  56. }
  57. protected abstract IntPtr CreateWindowCore();
  58. protected virtual void DestroyWindowCore()
  59. {
  60. if (_handle != IntPtr.Zero)
  61. {
  62. InteropMethods.DestroyWindow(_handle);
  63. _handle = IntPtr.Zero;
  64. }
  65. }
  66. protected virtual IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam) =>
  67. InteropMethods.DefWindowProc(hwnd, msg, wParam, lParam);
  68. public void EnsureHandle()
  69. {
  70. if (_handle == IntPtr.Zero)
  71. {
  72. if (!_isHandleCreationAllowed) return;
  73. _isHandleCreationAllowed = false;
  74. _handle = CreateWindowCore();
  75. if (IsWindowSubclassed) SubclassWndProc();
  76. }
  77. }
  78. protected override void DisposeNativeResources()
  79. {
  80. _isHandleCreationAllowed = false;
  81. DestroyWindowCore();
  82. DestroyWindowClassCore();
  83. }
  84. }