【学习笔记】C#之利用hook实现拾色器功能

C#之利用hook实现拾色器功能



一、HOOK的使用

引用dll实现对hook的调用,对鼠标操作进行全局监控。

 		[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool UnhookWindowsHookEx(int hhk);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr GetModuleHandle(string lpModuleName);

回调的函数部分代码

   private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
        {
            if (nCode >= 0 && wParam == (IntPtr)WM_LBUTTONDOWN)
            {
                //返回的数据类型
                MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
                Console.WriteLine($"Mouse Clicked at X: {hookStruct.pt.x}, Y: {hookStruct.pt.y},鼠标事件:{hookStruct.mouseData}{hookStruct.flags}");
                //MessageBox.Show($"Mouse Clicked at X: {hookStruct.pt.x}, Y: {hookStruct.pt.y}");


                MyEvent?.Invoke(this, EventArgs.Empty);
            }
            return CallNextHookEx(_hookID, nCode, wParam, lParam);
        }

二、取色的dll调用的关键引用

        [DllImport("user32.dll")]//取设备场景 
        private static extern IntPtr GetDC(IntPtr hwnd);//返回设备场景句柄 
        [DllImport("gdi32.dll")]//取指定点颜色 
        private static extern int GetPixel(IntPtr hdc, Point p);

三、取色部分代码

  private void Form1_Load(object sender, EventArgs e)
        {
            tim = new Timer() { Interval = 1 };
            tim.Tick += delegate
            {
                Point p = new Point(MousePosition.X, MousePosition.Y);//取置顶点坐标 
                IntPtr hdc = GetDC(new IntPtr(0));//取到设备场景(0就是全屏的设备场景) 
                int c = GetPixel(hdc, p);//取指定点颜色 
                r = (c & 0xFF);//转换R 
                g = (c & 0xFF00) / 256;//转换G 
                b = (c & 0xFF0000) / 65536;//转换B 
                textBox1.Text = $"{r},{g},{b}";
                pictureBox1.BackColor = Color.FromArgb(r, g, b);
                richTextBox1.Clear();
                richTextBox1.AppendText($"红(R):{r}\n绿(G):{g}\n蓝(B):{b}");
                richTextBox2.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(r)))), ((int)(((byte)(g)))), ((int)(((byte)(b)))));

            };

        }

功能展示

在这里插入图片描述

四、整体代码

//hook代码
class HookHelper
{
    //钩子类型
    private const int WH_MOUSE_LL = 14;
    private const int WM_LBUTTONDOWN = 0x0201;

    //钩子句柄
    private static int hookID = 0;

    private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);
    private static LowLevelMouseProc _proc; //用于回调

    private static IntPtr _hookID = IntPtr.Zero;

    public delegate void MyEventHandler(object sender, EventArgs e);
    public event MyEventHandler MyEvent;

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool UnhookWindowsHookEx(int hhk);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr GetModuleHandle(string lpModuleName);
    [StructLayout(LayoutKind.Sequential)]
    private struct MSLLHOOKSTRUCT
    {
        public POINT pt;
        public uint mouseData;
        public uint flags;
        public uint time;
        public IntPtr dwExtraInfo;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct POINT
    {
        public int x;
        public int y;
    }

    private static IntPtr SetHook(LowLevelMouseProc proc)
    {
        using (ProcessModule curModule = Process.GetCurrentProcess().MainModule)
        {
            return SetWindowsHookEx(WH_MOUSE_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
        }
    }

    private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
    {
        if (nCode >= 0 && wParam == (IntPtr)WM_LBUTTONDOWN)
        {
            //返回的数据类型
            MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
            Console.WriteLine($"Mouse Clicked at X: {hookStruct.pt.x}, Y: {hookStruct.pt.y}");
            MyEvent?.Invoke(this, EventArgs.Empty);
        }
        return CallNextHookEx(_hookID, nCode, wParam, lParam);
    }

    /// <summary>
    /// 键盘
    /// </summary>
    /// <param name="nCode"></param>
    /// <param name="wParam"></param>
    /// <param name="lParam"></param>
    /// <returns></returns>
    private const int WH_KEYBOARD_LL = 13;
    private const int WM_KEYDOWN = 0x0100;
    private const int WM_KEYUP = 0x0101;
    private static IntPtr HookCallbackKey(int nCode, IntPtr wParam, IntPtr lParam)
    {
        if (nCode >= 0 && (wParam == (IntPtr)WM_KEYDOWN || wParam == (IntPtr)WM_KEYUP))
        {
            int vkCode = Marshal.ReadInt32(lParam);

            if (wParam == (IntPtr)WM_KEYDOWN)
            {
                Console.WriteLine($"Key Down: {(Keys)vkCode}");
            }
            else if (wParam == (IntPtr)WM_KEYUP)
            {
                Console.WriteLine($"Key Up: {(Keys)vkCode}");
            }
        }
        MessageBox.Show("key运行");

        return CallNextHookEx(_hookID, nCode, wParam, lParam);
    }
    /// <summary>
    /// 安装hook
    /// </summary>
    /// <returns></returns>
    public void Start()
    {
        if (hookID == 0)
        {
            _proc = new LowLevelMouseProc(HookCallback);
            hookID = (int)SetHook(_proc);
            if (hookID == 0)
            {
                MessageBox.Show("hook 异常");
            }

        }

    }
    /// <summary>
    /// 卸载hook
    /// </summary>
    public void Stop()
    {
        if (hookID != 0)
        {
            UnhookWindowsHookEx(hookID);
            hookID = 0;
        }
    }

}
  //页面部分代码
  private Timer tim;
  private HookHelper hook;

  //颜色
  private int r;
  private int g;
  private int b;
  public Form1()
  {
      InitializeComponent();
    
      hook = new HookHelper();
      this.Text = "拾色器";
      this.FormClosed += Form1_FormClosed;

      // 设置窗口边框样式为 FixedSingle
      this.FormBorderStyle = FormBorderStyle.FixedSingle;
      // 禁用最大化按钮
      this.MaximizeBox = false;

  }

  private void Form1_FormClosed(object sender, FormClosedEventArgs e)
  {
      tim.Stop();
      hook.Stop();
  }

  [DllImport("user32.dll")]//取设备场景 
  private static extern IntPtr GetDC(IntPtr hwnd);//返回设备场景句柄 
  [DllImport("gdi32.dll")]//取指定点颜色 
  private static extern int GetPixel(IntPtr hdc, Point p);
  private void Form1_Load(object sender, EventArgs e)
  {
      tim = new Timer() { Interval = 1 };
      tim.Tick += delegate
      {
          Point p = new Point(MousePosition.X, MousePosition.Y);//取置顶点坐标 
          IntPtr hdc = GetDC(new IntPtr(0));//取到设备场景(0就是全屏的设备场景) 
          int c = GetPixel(hdc, p);//取指定点颜色 
          r = (c & 0xFF);//转换R 
          g = (c & 0xFF00) / 256;//转换G 
          b = (c & 0xFF0000) / 65536;//转换B 
          textBox1.Text = $"{r},{g},{b}";
          pictureBox1.BackColor = Color.FromArgb(r, g, b);
          richTextBox1.Clear();
          richTextBox1.AppendText($"红(R):{r}\n绿(G):{g}\n蓝(B):{b}");
          richTextBox2.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(r)))), ((int)(((byte)(g)))), ((int)(((byte)(b)))));

      };

  }

  private void button1_Click(object sender, EventArgs e)
  {
      tim.Stop();
      if (!tim.Enabled)
      {
          button1.Text = "颜色拾取";
          tim.Start();
          hook.MyEvent += button2_Click;
          hook.Start();
      }

  }

  private void button2_Click(object sender, EventArgs e)
  {

  }

  private void Form1_MouseDown(object sender, MouseEventArgs e)
  {
      // 判断是否是鼠标左键按下
      if (e.Button == MouseButtons.Left)
      {
          // 处理左键点击事件
          HandleLeftClick();
      }
      // 判断是否是鼠标右键按下
      else if (e.Button == MouseButtons.Right)
      {
          // 处理右键点击事件                
          HandleRightClick();
      }
  }
  private void HandleLeftClick()
  {
      if (tim.Enabled)
      {
          tim.Stop();
      }
  }

  private void HandleRightClick()
  {
      if (!tim.Enabled)
      {
          tim.Start();
      }
  }
  private void button2_Click_1(object sender, EventArgs e)
  {
      ColorDialog colorDialog = new ColorDialog();
      // 设置对话框的一些属性
      colorDialog.AllowFullOpen = true;  // 允许用户自定义颜色
      colorDialog.ShowHelp = true;        // 显示帮助按钮       
      if (colorDialog.ShowDialog() == DialogResult.OK)
      {
          // 获取所选颜色
          Color selectedColor = colorDialog.Color;
          // 在这里你可以使用 selectedColor 进行相应的操作
          // 例如,将颜色应用于控件或保存选定的颜色值等
          textBox1.Text = $"{selectedColor.R},{selectedColor.G},{selectedColor.B}";
          richTextBox1.AppendText($"红(R):{selectedColor.R}\n绿(G):{selectedColor.G}\n蓝(B):{selectedColor.B}");
          richTextBox2.BackColor = selectedColor;
          pictureBox1.BackColor = selectedColor;
      }
  }

  private void button3_Click(object sender, EventArgs e)
  {

      OpenFileDialog openFileDialog1 = new OpenFileDialog();
      openFileDialog1.CheckFileExists = true;
      openFileDialog1.CheckPathExists = true;
      openFileDialog1.FilterIndex = 2;
      openFileDialog1.Filter = "图片|*.jpg|*.bmp|*.jpeg|*.png|*.psd";


      if (openFileDialog1.ShowDialog() == DialogResult.OK)
      {
          string fileName = openFileDialog1.FileName;
          using (FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
          {
              Bitmap bitmap = new Bitmap(fileStream);
              pictureBox1.Image = bitmap;
              tim.Start();
          }
      }
  }

  private void button4_Click(object sender, EventArgs e)
  {
      SaveFileDialog saveFileDialog1 = new SaveFileDialog();
      saveFileDialog1.ValidateNames = true;
      saveFileDialog1.CreatePrompt = true;
      saveFileDialog1.DefaultExt = "txt";
      saveFileDialog1.Filter = "文本|*.txt";

      if (saveFileDialog1.ShowDialog() == DialogResult.OK)
      {
          string fileNamew = saveFileDialog1.FileName;
          using (StreamWriter writer = new StreamWriter(fileNamew))
          {
              writer.WriteLine($"红(R): {r} 绿(G):  {g} 蓝(B):  {b}  [{r},{g},{b}]");
          }

      }
  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值