// Author: Gockner, Simon // Created: 2021-04-07 // Copyright(c) 2021 SimonG. All Rights Reserved. using System; using System.ComponentModel; using System.Runtime.InteropServices; using Lib.NotifyIcon.Windows.Native.Types; namespace Lib.NotifyIcon.Windows.Native { internal abstract class NativeWindow { private const uint WS_POPUP = 0x80000000; // ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable private readonly WindowApi.WndProc _wndProc; //We need to store the window proc as a field so that it doesn't get garbage collected away private readonly string _className = "NativeHelperWindow" + Guid.NewGuid(); /// /// The window handle of the underlying native window /// public IntPtr Handle { get; } /// /// Creates a new native (Win32) helper window for receiving window messages /// protected NativeWindow() { _wndProc = WndProc; WndClassEx wndClassEx = new() { cbSize = Marshal.SizeOf(), lpfnWndProc = _wndProc, hInstance = WindowApi.GetModuleHandle(null), lpszClassName = _className }; ushort atom = WindowApi.RegisterClassEx(ref wndClassEx); if (atom == 0) throw new Win32Exception(); Handle = WindowApi.CreateWindowEx(0, atom, null, WS_POPUP, 0, 0, 0, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); if (Handle == IntPtr.Zero) throw new Win32Exception(); } /// /// Destructs the object and destroys the native window /// ~NativeWindow() { if (Handle != IntPtr.Zero) WindowApi.PostMessage(Handle, (uint) WindowsMessage.WmDestroy, IntPtr.Zero, IntPtr.Zero); } /// /// This function will receive all the system window messages relevant to our window /// protected virtual IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam) { switch (msg) { case (uint) WindowsMessage.WmClose: { WindowApi.DestroyWindow(hWnd); break; } case (uint) WindowsMessage.WmDestroy: { WindowApi.PostQuitMessage(0); break; } default: return WindowApi.DefWindowProc(hWnd, msg, wParam, lParam); } return IntPtr.Zero; } } }