C#颜色拾取器

1,目的:

  • 获取屏幕上任意位置像素的色值。

2,知识点:

  • 热键的注册与注销。
 /// <summary>
        /// 热键注册
        /// </summary>
        /// <param name="hWnd">要定义热键的窗口的句柄 </param>
        /// <param name="id">定义热键ID(不能与其它ID重复) </param>
        /// <param name="fsModifiers">标识热键是否在按Alt、Ctrl、Shift、Windows等键时才会生效 </param>
        /// <param name="vk">定义热键的内容 </param>
        /// <returns>如果函数执行成功,返回值不为0。如果函数执行失败,返回值为0。要得到扩展错误信息,调用GetLastError。</returns>
        [DllImport("user32.dll", SetLastError = true)]
        public static extern bool RegisterHotKey(IntPtr hWnd, int id, KeyModifiers fsModifiers, Keys vk);
        /// <summary>
        /// 热键注销
        /// </summary>
        /// <param name="hWnd">要取消热键的窗口的句柄  </param>
        /// <param name="id">要取消热键的ID </param>
        /// <returns></returns>
        [DllImport("user32.dll", SetLastError = true)]
        public static extern bool UnregisterHotKey(IntPtr hWnd, int id);
  • 颜色的获取。
/// <summary>
        /// 在一个指定设备场景中获取一个像素的RGB值
        /// </summary>
        /// <param name="hDC">设备场景的句柄</param>
        /// <param name="XPos">逻辑坐标中要检查点的X坐标</param>
        /// <param name="YPos">逻辑坐标中要检查点的Y坐标</param>
        /// <returns>返回一个32位包含ARGB的UInt</returns>
        [DllImport("gdi32.dll")]
        static public extern uint GetPixel(IntPtr hDC, int XPos, int YPos);
  • 获取的颜色值(32位Uint 数据类型),A ,R,G,B分布如下:

与常规A,R,G,B排序有所区别,而且获取的Alpha部分始终为0。

3,效果展示:

4,代码:

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        Timer t = new Timer() { Interval = 100 };
        IntPtr displayHwd;

        private void Form1_Load(object sender, EventArgs e)
        {
            APIHelper.RegisterHotKey(this.Handle, 81, KeyModifiers.Shift, Keys.C);
            this.TopMost = checkBox1.Checked;

            t.Tick += T_Tick;
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            APIHelper.UnregisterHotKey(this.Handle, 81);
        }
        /// <summary>
        /// 获取color从左至右第4个byte作为Blue值
        /// </summary>
        /// <param name="color"></param>
        /// <returns></returns>
        byte GetBlue(uint color)
        {
            return (byte)(color>>16);
        }
        byte GetGreen(uint color)
        {
            //向右移动8位
            return (byte)(color >> 8);
        }
        byte GetRed(uint color)
        {
            
            return (byte)(color);
        }
        byte GetAlpha(uint color)
        {
            return (byte)(color >> 24);
        }

        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            this.TopMost = checkBox1.Checked;
        }

        private void btnExit_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            if (btnStart.Text == "开始")
            {
                t.Start();
                btnStart.BackColor = Color.LightGreen;
                btnStart.Text = "停止";
              displayHwd=   APIHelper.CreateDC("DISPLAY", null, null, IntPtr.Zero);
            }
            else
            {
                btnStart.Text = "开始";
                t.Stop();
                btnStart.BackColor = SystemColors.Control;
                APIHelper.DeleteDC(displayHwd);
            }
            

               
        }
        protected override void WndProc(ref Message m)
        {
            //WM_HOTKEY=0x0312,热键关联的消息ID
            const int WM_HOTKEY = 0x0312;
            //按快捷键     
            switch (m.Msg)
            {
                case WM_HOTKEY:
                    switch (m.WParam.ToInt32())
                    {
                        case 81:    //按下的是Shift+C  
                            Clipboard.SetText(txtColor.Text);
                            break;
                    }
                    break;
            }
            base.WndProc(ref m);
        }
        List<string> list = new List<string>();
        private void T_Tick(object sender, EventArgs e)
        {
            Point mousePoint=  Control.MousePosition;
            txtPoint.Text = $"X:{mousePoint.X},Y:{mousePoint.Y}";
            if(Control.MouseButtons== MouseButtons.Left)
            {

                uint colorVal = APIHelper.GetPixel(displayHwd, mousePoint.X, mousePoint.Y);
                list.Clear();
                

                byte[] bytes = BitConverter.GetBytes(colorVal);
                BitArray array = new BitArray(bytes);
                foreach (bool bit in array)
                {
                    if (bit)
                    {
                        list.Add("1");
                    }
                    else
                    {
                        list.Add("0");
                    }

                }
                list.Reverse();
                txtMonitor.Text = string.Join(" ", list);
                byte red = GetRed(colorVal);
                byte green = GetGreen(colorVal);
                byte blue = GetBlue(colorVal);
                byte alpha = GetAlpha(colorVal);
                panel1.BackColor = Color.FromArgb( red, green, blue);
                txtColor.Text = ColorTranslator.ToHtml(panel1.BackColor).ToString();
                txtRGB.Text = $"{red},{green},{blue}";
                btnStart.Text = "开始";
                t.Stop();
                btnStart.BackColor = SystemColors.Control;
                APIHelper.DeleteDC(displayHwd);
            }
        }
    }
    [Flags()]
    public enum KeyModifiers
    {
        None = 0,
        Alt = 1,
        Ctrl = 2,
        Shift = 4,
        WindowsKey = 8
    }
    class APIHelper
    {
        /// <summary>
        /// 在一个指定设备场景中获取一个像素的RGB值
        /// </summary>
        /// <param name="hDC">设备场景的句柄</param>
        /// <param name="XPos">逻辑坐标中要检查点的X坐标</param>
        /// <param name="YPos">逻辑坐标中要检查点的Y坐标</param>
        /// <returns>返回一个32位包含ARGB的UInt</returns>
        [DllImport("gdi32.dll")]
        static public extern uint GetPixel(IntPtr hDC, int XPos, int YPos);
        /// <summary>
        /// 为专门设备创建设备场景
        /// </summary>
        /// <param name="driverName">如果此参数为DISPLAY则代表整个屏幕的设备场景,如果为WINSPOOL则访问打印机驱动</param>
        /// <param name="deviceName">所用专门设备的名称</param>
        /// <param name="output">用null给该参数</param>
        /// <param name="lpinitData">DEVMODE,该结构保存初始值</param>
        /// <returns>设备场景的句柄</returns>
        [DllImport("gdi32.dll")]
        static public extern IntPtr CreateDC(string driverName, string deviceName, string output, IntPtr lpinitData);
        /// <summary>
        /// 在一个指定设备场景中获取一个像素的RGB值
        /// </summary>
        /// <param name="DC">设备场景的句柄</param>
        /// <returns></returns>
        [DllImport("gdi32.dll")]
        static public extern bool DeleteDC(IntPtr DC);
        /// <summary>
        /// 热键注册
        /// </summary>
        /// <param name="hWnd">要定义热键的窗口的句柄 </param>
        /// <param name="id">定义热键ID(不能与其它ID重复) </param>
        /// <param name="fsModifiers">标识热键是否在按Alt、Ctrl、Shift、Windows等键时才会生效 </param>
        /// <param name="vk">定义热键的内容 </param>
        /// <returns>如果函数执行成功,返回值不为0。如果函数执行失败,返回值为0。要得到扩展错误信息,调用GetLastError。</returns>
        [DllImport("user32.dll", SetLastError = true)]
        public static extern bool RegisterHotKey(IntPtr hWnd, int id, KeyModifiers fsModifiers, Keys vk);
        /// <summary>
        /// 热键注销
        /// </summary>
        /// <param name="hWnd">要取消热键的窗口的句柄  </param>
        /// <param name="id">要取消热键的ID </param>
        /// <returns></returns>
        [DllImport("user32.dll", SetLastError = true)]
        public static extern bool UnregisterHotKey(IntPtr hWnd, int id);

       
    }

相关推荐

  1. C++拾遗(三) 引用

    2024-01-28 11:12:02       29 阅读
  2. C语言拾遗

    2024-01-28 11:12:02       20 阅读
  3. js+css实现颜色选择

    2024-01-28 11:12:02       37 阅读
  4. [Godot] 3D拾取

    2024-01-28 11:12:02       13 阅读
  5. WebGL之使用着色颜色应用于 WebGL

    2024-01-28 11:12:02       17 阅读
  6. C++拾遗(四)引用与指针

    2024-01-28 11:12:02       27 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-01-28 11:12:02       19 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-01-28 11:12:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-01-28 11:12:02       20 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-01-28 11:12:02       20 阅读

热门阅读

  1. uniapp-app使用富文本编辑器editor

    2024-01-28 11:12:02       32 阅读
  2. RUST笔记: 动态链接库的创建和使用

    2024-01-28 11:12:02       41 阅读
  3. Springboot多数据源连接

    2024-01-28 11:12:02       42 阅读
  4. ValueConverters.NET

    2024-01-28 11:12:02       34 阅读
  5. 初识Cargo-Rust的包管理器

    2024-01-28 11:12:02       37 阅读
  6. 轻松将Word文档转换为PDF:R语言实战教程

    2024-01-28 11:12:02       35 阅读
  7. 面试 HTML 框架八股文十问十答第一期

    2024-01-28 11:12:02       44 阅读
  8. 300. 最长递增子序列(动态规划)

    2024-01-28 11:12:02       33 阅读