程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#:Win32 Hooks(一)讓下一個彈出子窗體自動顯示在父窗體中心

C#:Win32 Hooks(一)讓下一個彈出子窗體自動顯示在父窗體中心

編輯:C#入門知識

/* ----------------------------------------------------------
文件名稱:FormHelper.cs

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(); 
        } 
    } 

 

摘自 秦建輝的專欄

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved