自定义扩展颜色对话框

这个是我利用底层钩子技术扩展的一个颜色对话框,下面就分析代码:

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Drawing;
using CustomCommonDialog;
using AlphaSliderControl;
using System.Diagnostics;

namespace CustomCommonDialog
{
    public class FColorDialog : ColorDialog
    {
        //API函数:获取指定句柄的类名
        [DllImport("User32.dll", CharSet = CharSet.Auto)]
        public static extern int GetClassName(IntPtr hwnd, char[] className, int maxCount);

        //API函数:根据指定句柄,寻找下一个句柄
        [DllImport("User32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr GetWindow(IntPtr hwnd, int uCmd);

        //API函数:设置指定句柄对象的Text值
        [DllImport("User32.dll", CharSet = CharSet.Auto)]
        public static extern bool SetWindowText(IntPtr hwnd, char[] lpString);


        bool ButtonTextChanged = false;


        // the CHOOSECOLOR structure, used to control the appearance and behaviour of the OpenFileDialog
       
        private Panel _panelAlpha= new Panel();


        public FColorDialog()
        {
            Button b = new Button();
            b.Text = "自定义按钮";
            b.Click += new System.EventHandler(OnBtnClick);
            _panelAlpha.Controls.Add(b);
            _panelAlpha.Width = 100;
            _panelAlpha.BackColor = Color.Green;
            base.FullOpen = true;
        }

        private void OnBtnClick(object sender, EventArgs e)
        {
            MessageBox.Show("Button was clicked");
            base.Color = Color.Red;
        }

        //查找句柄为hWnd的窗口内的控件,并把第一个类名为"Button"的空件的名字修改
        public void FixButtonText(IntPtr hWnd)
        {
            //如果句柄hWnd为空,则取消操作
            if (hWnd == IntPtr.Zero) return;

            try
            {
                //API函数GetWindow的参数:查找下一个同级句柄
                int GW_HWNDNEXT = 2;
                //API函数GetWindow的参数:查找子级句柄的第一个句柄
                int GW_CHILD = 5;

                //获取hWnd的第一个子控件句柄
                IntPtr pWnd = GetWindow(hWnd, GW_CHILD);
                while (pWnd != IntPtr.Zero)
                {
                    char[] className = new char[255];
                    int classNamelength = GetClassName(pWnd, className, 255);
                    string classNameStr = new string(className, 0, classNamelength);    //获取句柄对应的类名

                    //如果是Button类,则修改文字
                    if (classNameStr == "Button")
                    {
                        SetWindowText(pWnd, ("Febotion.com\0").ToCharArray());

                        //标记修改完成
                        ButtonTextChanged = true;
                        break;
                    }
                    else
                    {
                        //不是Button类,则继续寻找下一个控件句柄
                        pWnd = GetWindow(pWnd, GW_HWNDNEXT);
                    }
                }
            }
            catch { }
        }

        //重载ColorDialog的消息钩子
        protected override IntPtr HookProc(IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam)
        {

            // return if invalid window
            if (hWnd == IntPtr.Zero)
                return IntPtr.Zero;

            //如果消息句柄不为0,且修改完成标记不为true,则执行修改函数
            if (hWnd != IntPtr.Zero && !ButtonTextChanged)
            {
                FixButtonText(hWnd);
            }

            switch (msg)
            {

                  case WindowMessage.InitDialog:
                    {
       
                        POINT topLeft = new POINT();
                        POINT bottomRight = new POINT();

       //设定当前需要扩展的面板的母面板为HWND句柄
                        NativeMethods.SetParent(_panelAlpha.Handle, hWnd);
                        RECT rc = new RECT();

                       //根据母面板的句柄获取当前母面板的大小的矩形
                        NativeMethods.GetWindowRect(hWnd, ref rc);

                       //设置空间的位置
                        topLeft.X = rc.right;
                        topLeft.Y = rc.top;
                        NativeMethods.ScreenToClient(hWnd, ref topLeft);
                        bottomRight.X = rc.right;
                        bottomRight.Y = rc.bottom;
                        NativeMethods.ScreenToClient(hWnd, ref bottomRight);

       //设置子面板的高度
                        _panelAlpha.Height = rc.bottom - rc.top;

                        Rectangle rcClient = _panelAlpha.ClientRectangle;
                        //改变面板的大小

       NativeMethods.MoveWindow(hWnd, rc.left, rc.top, bottomRight.X + rcClient.Width+11 , bottomRight.Y + 35 , true);

                         return IntPtr.Zero;
                    }
                // WM_SIZE - the OpenFileDialog has been resized, so we'll resize the content and user-supplied
                // panel to fit nicely
                case WindowMessage.Size:
                    {
                        PlaceCustomControls(hWnd);
                        return IntPtr.Zero;
                        //break;
                    }

            }

            return base.HookProc(hWnd, msg, wparam, lparam);
        }

            // <summary>
  /// Layout the content of the ChooseColorDialog, according to the overall size of the dialog
  /// </summary>
  /// <param name="hWnd">handle of window that received the WM_SIZE message</param>
  private void PlaceCustomControls( IntPtr hWnd )
  {
   IntPtr hWndParent = NativeMethods.GetParent( hWnd );
   NativeMethods.SetParent( _panelAlpha.Handle, hWnd);
   RECT rc = new RECT();
   NativeMethods.GetWindowRect( hWnd, ref rc );
   POINT topLeft;
   topLeft.X = rc.right;
   topLeft.Y = rc.top;
   NativeMethods.ScreenToClient( hWnd, ref topLeft );
   POINT bottomRight;
   bottomRight.X = rc.right;
   bottomRight.Y = rc.bottom;
   NativeMethods.ScreenToClient( hWnd, ref bottomRight );

   Rectangle rcClient = _panelAlpha.ClientRectangle;// .ClientRectangle();
            NativeMethods.MoveWindow(_panelAlpha.Handle, rc.right - rc.left - rcClient.Width - 10, 0, rcClient.Width, rcClient.Height, true);

        }


    }
}
转自:http://zhouweigang01.blog.163.com/blog/static/934090720071030154147/

原文地址:https://www.cnblogs.com/zhangpengshou/p/1699848.html