C# winform 启动前为所有的Form设置统一的Icon

本文为frozleaf原创文章,原文地址:https://blog.csdn.net/frozleaf/article/details/89429629

思路:

通过SetWindowsHookEx函数,获取所有的Form对象,修改其Icon属性。

实现:

public class WindowHooker
    {
        /// <summary>
        /// 页面统一图标
        /// 创建时间:2019.08.21
        /// </summary>
        public class HookControlEventArgs : EventArgs
        {
            public Control Control;

            public HookControlEventArgs(Control c)
            {
                this.Control = c;
            }
        }

        #region win32 api
        internal delegate IntPtr HOOKPROC(int nCode, IntPtr wParam, IntPtr lParam);
        [DllImport("User32.dll", CharSet = CharSet.Auto)]
        internal static extern IntPtr SetWindowsHookEx(int idHook, HOOKPROC lpfn, int hMod, int dwThreadId);
        [DllImport("User32.dll", CharSet = CharSet.Auto)]
        internal static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
        #endregion

        internal IntPtr PHook = IntPtr.Zero;
        internal HOOKPROC PHookProc = null;

        public event EventHandler<HookControlEventArgs> OnHookControl;

        public void Hook()
        {
            PHookProc = new HOOKPROC(FnHookProc);
            // 如果代码改为:SetWindowsHookEx(5, FnHookProc, 0, AppDomain.GetCurrentThreadId());
            // 则会报如下错误:
            // ”类型的已垃圾回收委托进行了回调。这可能会导致应用程序崩溃、损坏和数据丢失。向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们。”
            PHook = SetWindowsHookEx(5, PHookProc, 0, AppDomain.GetCurrentThreadId());
        }

        private IntPtr FnHookProc(int nCode, IntPtr wParam, IntPtr lParam)
        {
            switch (nCode)
            {
                case 5:
                    {
                        var control = Control.FromHandle(wParam);
                        if (control != null)
                        {
                            var frm = control as Form;
                            if (frm != null)
                            {
                                if (OnHookControl != null)
                                {
                                    OnHookControl(this, new HookControlEventArgs(frm));
                                }
                            }
                        }
                        break;
                    }
            }
            return CallNextHookEx(PHook, nCode, wParam, lParam);
        }
    }

调用

/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    //---
    WindowHooker hooker = new WindowHooker();
    hooker.OnHookControl += (o, e) => {
        Console.WriteLine(e.Control.GetType().ToString());
        var frm = e.Control as Form;
        //指定图标路径
        frm.Icon = GetResAsIcon("app.ico");
        //使用系统图标(二者根据自身情况使用)
    	frm.Icon = Icon.ExtractAssociatedIcon(Application.ExecutablePath);
    };
    hooker.Hook();
    Application.Run(new FrmMain());
}
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页