C#:Win32 Hooks(一)让下一个弹出子窗体自动显示在父窗体中心

/* ---------------------------------------------------------- 文件名称:FormHelper.cs 作者:秦建辉 MSN:splashcn@msn.com QQ:36748897 博客:http://blog.csdn.net/jhqin 开发环境: Visual Studio V2010 .NET Framework 4 Client Profile 版本历史: V1.0 2012年05月07日 优化参考代码 参考资料: http://www.jasoncarr.com/technology/centering-a-message-box-on-the-active-window-in-csharp http://stackoverflow.com/questions/1732443/center-messagebox-in-parent-form ------------------------------------------------------------ */ using System; using System.Runtime.InteropServices; using System.Windows.Forms; namespace Splash.Windows.Forms { /// <summary> /// 窗体扩展功能: /// 1.让下一个弹出子窗体自动显示在父窗体中心 /// </summary> public static class FormHelper { /// <summary> /// 子窗体自动显示在父窗体中心位置 /// </summary> /// <param name="owner">要中心化子窗体的窗体</param> /// <remarks>扩展方法</remarks> public static void CenterChild(this IWin32Window owner) { CenterChildHelper helper = new CenterChildHelper(); helper.Run(owner); } /// <summary> /// 基于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; // 钩子句柄 private IntPtr _parent; // 父窗体句柄 private GCHandle _gch; public void Run(IWin32Window owner) { NativeMethods.CBTProc CenterChildHookProc = new NativeMethods.CBTProc(CenterChildCallBack); // 分配新的GCHandle,保护对象不被垃圾回收 _gch = GCHandle.Alloc(CenterChildHookProc); _parent = owner.Handle; // 父窗体句柄 // 注意:dwThreadId为System.Threading.Thread.CurrentThread.ManagedThreadId不起作用 _hhk = NativeMethods.SetWindowsHookEx(WH_CBT, CenterChildHookProc, IntPtr.Zero, NativeMethods.GetCurrentThreadId()); } private IntPtr CenterChildCallBack(Int32 nCode, IntPtr wParam, IntPtr lParam) { if (nCode == HCBT_ACTIVATE) { // 父窗体 NativeMethods.RECT formRect; NativeMethods.GetWindowRect(_parent, out formRect); // 子窗体 NativeMethods.RECT messageBoxRect; NativeMethods.GetWindowRect(wParam, out messageBoxRect); Int32 width = messageBoxRect.right - messageBoxRect.left; // 消息窗体宽度 Int32 height = messageBoxRect.bottom - messageBoxRect.top; // 消息窗体高度 Int32 xPos = (formRect.left + formRect.right - width) >> 1; // 消息窗体位于父窗体中心时左上角X坐标 Int32 yPos = (formRect.top + formRect.bottom - height) >> 1; // 消息窗体位于父窗体中心时左上角Y坐标 // 将消息窗体移到父窗体中心 NativeMethods.MoveWindow(wParam, xPos, yPos, width, height, false); // 卸载钩子 NativeMethods.UnhookWindowsHookEx(_hhk); // 释放已分配的GCHandle _gch.Free(); } // 允许操作 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委托声明 /// </summary> /// <param name="nCode">HCBT_ACTIVATE:系统将要激活一个窗口</param> /// <param name="wParam">要激活的窗口句柄</param> /// <param name="lParam">指向CBTACTIVATESTRUCT结构</param> /// <returns> /// 0:执行这个操作 /// 1:阻止这个操作 /// </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: MarshalAs(UnmanagedType.Bool)] internal static extern Boolean UnhookWindowsHookEx(IntPtr hhk); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] internal static extern Boolean GetWindowRect(IntPtr hWnd, out RECT lpRect); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] internal static extern Boolean MoveWindow(IntPtr hWnd, Int32 X, Int32 Y, Int32 nWidth, Int32 nHeight, [MarshalAs(UnmanagedType.Bool)]Boolean bRepaint); [DllImport("kernel32.dll")] internal static extern Int32 GetCurrentThreadId(); } } }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值