/// <summary> /// Initializes a new instance of the <see cref="WindowSubclassHandler"/> class. /// </summary> /// <param name="handle">The window handle of the window to subclass.</param> public WindowSubclassHandler(IntPtr handle) { _handle = handle.OrThrowIfZero(); // Create a delegate for our window procedure and get a function // pointer for it. _windowProcDelegate = NativeWndProc; _windowProcDelegatePtr = Marshal.GetFunctionPointerForDelegate( _windowProcDelegate); }
/// <summary> /// Initializes a new instance of the <see cref="WindowSubclassHandler"/> class. /// </summary> /// <param name="handle">The window handle of the window to subclass.</param> public WindowSubclassHandler(IntPtr handle) { if (handle == IntPtr.Zero) { throw new ArgumentNullException(nameof(handle)); } _handle = handle; // Create a delegate for our window procedure and get a function // pointer for it. _windowProcDelegate = NativeWndProc; _windowProcDelegatePtr = Marshal.GetFunctionPointerForDelegate( _windowProcDelegate); }
/// <summary> /// Once the classname and style bits have been set, this can be called to register the class. /// </summary> private unsafe void RegisterClass() { User32.WNDCLASS windowClass = new User32.WNDCLASS(); string localClassName = _className; if (localClassName == null) { // If we don't use a hollow brush here, Windows will "pre paint" us with COLOR_WINDOW which // creates a little bit if flicker. This happens even though we are overriding wm_erasebackgnd. // Make this hollow to avoid all flicker. windowClass.hbrBackground = Gdi32.GetStockObject(Gdi32.StockObject.HOLLOW_BRUSH); windowClass.style = _classStyle; _defaultWindProc = DefaultWindowProc; localClassName = "Window." + Convert.ToString((int)_classStyle, 16); } else { // A system defined Window class was specified, get its info if (!User32.GetClassInfoW(NativeMethods.NullHandleRef, _className, ref windowClass)) { throw new Win32Exception(Marshal.GetLastWin32Error(), SR.InvalidWndClsName); } localClassName = _className; _defaultWindProc = windowClass.lpfnWndProc; } _windowClassName = GetFullClassName(localClassName); _windProc = new User32.WNDPROC(Callback); windowClass.lpfnWndProc = Marshal.GetFunctionPointerForDelegate(_windProc); windowClass.hInstance = Kernel32.GetModuleHandleW(null); fixed(char *c = _windowClassName) { windowClass.lpszClassName = c; if (User32.RegisterClassW(ref windowClass) == 0) { _windProc = null; throw new Win32Exception(); } } }
internal void AssignHandle(IntPtr handle, bool assignUniqueID) { lock (this) { CheckReleased(); Debug.Assert(handle != IntPtr.Zero, "handle is 0"); Handle = handle; _priorWindowProcHandle = User32.GetWindowLong(this, User32.GWL.WNDPROC); Debug.Assert(_priorWindowProcHandle != IntPtr.Zero); Debug.WriteLineIf( WndProcChoice.TraceVerbose, WndProcShouldBeDebuggable ? "Using debuggable wndproc" : "Using normal wndproc"); _windowProc = new User32.WNDPROC(Callback); AddWindowToTable(handle, this); // Set the NativeWindow window procedure delegate and get back the native pointer for it. User32.SetWindowLong(this, User32.GWL.WNDPROC, _windowProc); _windowProcHandle = User32.GetWindowLong(this, User32.GWL.WNDPROC); // This shouldn't be possible. Debug.Assert(_priorWindowProcHandle != _windowProcHandle, "Uh oh! Subclassed ourselves!!!"); if (assignUniqueID && (unchecked ((int)((long)User32.GetWindowLong(this, User32.GWL.STYLE))) & NativeMethods.WS_CHILD) != 0 && unchecked ((int)((long)User32.GetWindowLong(this, User32.GWL.ID))) == 0) { User32.SetWindowLong(this, User32.GWL.ID, handle); } if (_suppressedGC) { GC.ReRegisterForFinalize(this); _suppressedGC = false; } OnHandleChange(); } }
/// <summary> /// Constructor. /// </summary> /// <param name="className">Name, or default will be generated.</param> /// <param name="moduleInstance">Module to associate with the window. The entry assembly is the default.</param> /// <param name="backgroundBrush">Use (IntPtr)(-1) for no background brush.</param> /// <param name="icon">Use (IntPtr)(-1) for no icon.</param> /// <param name="cursor">Use (IntPtr)(-1) for no cursor.</param> /// <param name="menuName">Menu name, can not set with <paramref name="menuId"/>.</param> /// <param name="menuId">Menu id, can not set with <paramref name="menuName"/>.</param> public unsafe WindowClass( string className = default, IntPtr moduleInstance = default, User32.CS classStyle = User32.CS.HREDRAW | User32.CS.VREDRAW, IntPtr backgroundBrush = default, IntPtr icon = default, IntPtr cursor = default, string menuName = null, int menuId = 0, int classExtraBytes = 0, int windowExtraBytes = 0) { // Handle default values className ??= Guid.NewGuid().ToString(); if (backgroundBrush == default) { backgroundBrush = User32.GetSysColorBrush(COLOR_WINDOW); } else if (backgroundBrush == (IntPtr)(-1)) { backgroundBrush = default; } if (icon == default) { icon = LoadIconW(IntPtr.Zero, (IntPtr)IDI_APPLICATION); } else if (icon == (IntPtr)(-1)) { icon = default; } if (cursor == default) { cursor = User32.LoadCursorW(IntPtr.Zero, (IntPtr)User32.CursorResourceId.IDC_ARROW); } else if (cursor == (IntPtr)(-1)) { cursor = default; } if (moduleInstance == IntPtr.Zero) { Marshal.GetHINSTANCE(Assembly.GetCallingAssembly().Modules.First()); } if (menuId != 0 && menuName != null) { throw new ArgumentException($"Can't set both {nameof(menuName)} and {nameof(menuId)}."); } _windowProcedure = WNDPROC; ModuleInstance = moduleInstance; _className = className; _menuName = menuName ?? string.Empty; _wndClass = new User32.WNDCLASS { style = classStyle, lpfnWndProc = Marshal.GetFunctionPointerForDelegate(_windowProcedure), cbClsExtra = classExtraBytes, cbWndExtra = windowExtraBytes, hInstance = moduleInstance, hIcon = icon, hCursor = cursor, hbrBackground = backgroundBrush, lpszMenuName = (char *)menuId }; }