/*----------------------------------------------------------
File Name: FormHelper. cs
Using System;
Using System. Runtime. InteropServices;
Using System. Windows. Forms;
Namespace Splash. Windows. Forms
{
/// <Summary>
/// Form extension:
/// 1. The child form is automatically displayed in the center of the parent form
/// </Summary>
Public static class FormHelper
{
/// <Summary>
/// The child form is automatically displayed in the center of the parent form
/// </Summary>
/// <Param name = "owner"> form to center the subform </param>
/// <Remarks> Extension Method </remarks>
Public static void CenterChild (this IWin32Window owner)
{
CenterChildHelper helper = new CenterChildHelper ();
Helper. Run (owner );
}
/// <Summary>
/// Automatically display sub-forms in the center of the parent form based on Hook
/// </Summary>
Private class CenterChildHelper
{
Private const Int32 WH_CBT = 5;
Private const Int32 HCBT_ACTIVATE = 5;
Private const Int32 GWL_HINSTANCE =-6;
Private IntPtr _ hhk; // hook handle
Private IntPtr _ parent; // parent form handle
Private GCHandle _ gch;
Public void Run (IWin32Window owner)
{
NativeMethods. CBTProc CenterChildHookProc = new NativeMethods. CBTProc (CenterChildCallBack );
// Allocate a new GCHandle to prevent objects from being recycled.
_ Gch = GCHandle. Alloc (CenterChildHookProc );
_ Parent = owner. Handle; // parent form Handle
// Note: dwThreadId is System. Threading. Thread. CurrentThread. ManagedThreadId does not work
_ Hhk = NativeMethods. SetWindowsHookEx (WH_CBT, CenterChildHookProc, IntPtr. Zero, NativeMethods. GetCurrentThreadId ());
}
Private IntPtr CenterChildCallBack (Int32 nCode, IntPtr wParam, IntPtr lParam)
{
If (nCode = HCBT_ACTIVATE)
{// Parent form
NativeMethods. RECT formRect;
NativeMethods. GetWindowRect (_ parent, out formRect );
// Subform
NativeMethods. RECT messageBoxRect;
NativeMethods. GetWindowRect (wParam, out messageBoxRect );
Int32 width = messageBoxRect. right-messageBoxRect. left; // message form width
Int32 height = messageBoxRect. bottom-messageBoxRect. top; // message form height
Int32 xPos = (formRect. left + formRect. right-width)> 1; // The X coordinate in the upper left corner of the message form in the center of the parent form
Int32 yPos = (formRect. top + formRect. bottom-height)> 1; // Y coordinate of the message form in the upper left corner of the center of the parent form
// Move the message form to the center of the parent form
NativeMethods. MoveWindow (wParam, xPos, yPos, width, height, false );
// Uninstall the hook
NativeMethods. UnhookWindowsHookEx (_ hhk );
// Release the allocated GCHandle
_ Gch. Free ();
}
// Allow operations
Return IntPtr. Zero;
}
}
Private static class NativeMethods
{
[StructLayout (LayoutKind. Sequential)]
Internal struct RECT
{
Public Int32 left;
Public Int32 top;
Public Int32 right;
Public Int32 bottom;
}
/// <Summary>
/// CBTProc delegation statement
/// </Summary>
/// <Param name = "nCode"> HCBT_ACTIVATE: the system will activate a window. </param>
/// <Param name = "wParam"> the window handle to be activated </param>
/// <Param name = "lParam"> point to the CBTACTIVATESTRUCT structure </param>
/// <Returns>
/// 0: execute this operation
/// 1: block this operation
/// </Returns>
Internal delegate IntPtr CBTProc (Int32 nCode, IntPtr wParam, IntPtr lParam );
[DllImport ("user32.dll", SetLastError = true)]
Internal static extern IntPtr SetWindowsHookEx (Int32 idHook, CBTProc lpfn, IntPtr hMod, Int32 dwThreadId );
[DllImport ("user32.dll")]
[Return: financialas (UnmanagedType. Bool)]
Internal static extern Boolean UnhookWindowsHookEx (IntPtr hhk );
[DllImport ("user32.dll")]
[Return: financialas (UnmanagedType. Bool)]
Internal static extern Boolean GetWindowRect (IntPtr hWnd, out RECT lpRect );
[DllImport ("user32.dll")]
[Return: financialas (UnmanagedType. Bool)]
Internal static extern Boolean MoveWindow (IntPtr hWnd, Int32 X, Int32 Y, Int32 nWidth, Int32 nHeight, [financialas (UnmanagedType. Bool)] Boolean bRepaint );
[DllImport ("kernel32.dll")]
Internal static extern Int32 GetCurrentThreadId ();
}
}
}
From Qin Jianhui's column