private void HookWindowProc(IntPtr hwnd, NativeStructs.WndProc newWndProc, IntPtr oldWndProc) { _hwndAttached = hwnd; _hwndHandleRef = new HandleRef(null, _hwndAttached); _bond = Bond.Attached; _attachedWndProc = newWndProc; _oldWndProc = oldWndProc; IntPtr oldWndProc2 = NativeMethods.SetWindowLong(_hwndAttached, NativeConstants.GWL_WNDPROC, _attachedWndProc); // Track this window so that we can rip out the managed window proc // when the CLR shuts down. ManagedWndProcTracker.TrackHwnd(_hwndAttached); }
/// <summary> /// This method subclasses the specified window, such that the /// delegate specified to the constructor will be called to process /// the messages that are sent or posted to this window. /// </summary> /// <param name="hwnd"> /// The window to subclass. /// </param> /// <returns> /// An identifier that can be used to reference this instance of /// the HwndSubclass class in the static RequestDetach method. /// </returns> public IntPtr Attach(IntPtr hwnd) { if (hwnd == IntPtr.Zero) { throw new ArgumentNullException("hwnd"); } if (_bond != Bond.Unattached) { throw new InvalidOperationException(); } NativeStructs.WndProc newWndProc = new NativeStructs.WndProc(SubclassWndProc); IntPtr oldWndProc = NativeMethods.GetWindowLong(hwnd, NativeConstants.GWL_WNDPROC); HookWindowProc(hwnd, newWndProc, oldWndProc); // Return the GC handle as a unique identifier of this return((IntPtr)_gcHandle); }
/// <summary> /// This method unsubclasses this HwndSubclass object from the window /// it previously subclassed. The HwndSubclass object is not thread /// safe, and should thus be called only by the thread that owns /// the window being unsubclassed. /// </summary> /// <param name="force"> /// Whether or not the unsubclassing should be forced. Due to the /// way that Win32 implements window subclassing, it is not always /// possible to safely remove a window proc from the WNDPROC chain. /// However, the delegate will not be called again after this /// method returns. /// </param> /// <returns> /// Whether or not this HwndSubclass object was actually removed from /// the WNDPROC chain. /// </returns> public bool Detach(bool force) { bool detached = false; bool cleanup = force; // If we have already detached, return immediately. if (_bond == Bond.Detached || _bond == Bond.Unattached) { detached = true; } else { // When we detach, we simply make a note of it. _bond = Bond.Orphaned; // If we aren't going to force our removal from the window proc chain, // at least check to see if we can safely remove us. if (!force) { NativeStructs.WndProc currentWndProc = NativeMethods.GetWindowLongWndProc(_hwndAttached, NativeConstants.GWL_WNDPROC); //AvDebug.Assert(currentWndProc != null, "A window should always have a window proc."); // If the current window proc is us, then we can clean up. if (currentWndProc == _attachedWndProc) { cleanup = true; } } // Cleanup if we can. if (cleanup) { Dispose(); detached = true; } } return(detached); }