• 利用Windows API实现屏幕取色器


    一  效果图

      为了实现这个取色器,在网上查了很多关于取色器的资料,起先是通过winform怎么制作,后来发现大多数资料都调用了windows api,但自己以前从来没有用过这方面的,又从网上下了windows api 来看,经过多次实践终于做出了现在这个效果,先感谢下网上那些提供资料的朋友。

      效果,如下图:

      

    二 原理

      为了实现整个屏幕取色

      1.需要获取鼠标当前的位置

      2.获取整个窗口的场景

      3.获取指定点的颜色值

      4.判断按键状态来控制开始结束取色

      需要实现这些功能,就必需要调用windows api来实现。

      在C#中调用windows api的方式如下所示:

    [DllImport("user32.dll")]
    public static extern uint WindowFromPoint(uint x_point,uint y_point);

    三 详细代码

      关键代码都已经注释,就不解释了。界面代码就不给出了很简单的。

    代码
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;

    namespace GetColor
    {
    public partial class colorForm : Form
    {
    private int redValue = 255;
    private int greenValue = 255;
    private int blueValue = 255;

    public colorForm()
    {
    InitializeComponent();

    InitPanelColor();
    }

    private bool flag = false;

    public struct POINTAPI
    {
    public uint x;
    public uint y;
    }

    public class WinInfo
    {
    /// <summary>
    /// 返回包含了指定点的窗口的句柄
    /// </summary>
    /// <param name="x_point"></param>
    /// <param name="y_point"></param>
    /// <returns></returns>
    [DllImport("user32.dll")]
    public static extern uint WindowFromPoint(uint x_point,uint y_point);

    /// <summary>
    /// 获取鼠标指针当前位置
    /// </summary>
    /// <param name="p"></param>
    /// <returns></returns>
    [DllImport("user32.dll")]
    public static extern bool GetCursorPos(ref POINTAPI p);

    /// <summary>
    /// 判断屏幕上一个指定点的客户区坐标
    /// </summary>
    /// <param name="hwnd">一个窗口的句柄,该窗口定义了要使用的客户区坐标系统</param>
    /// <param name="p"></param>
    /// <returns></returns>
    [DllImport("user32.dll")]
    public static extern uint ScreenToClient(uint hwnd,ref POINTAPI p);


    /// <summary>
    /// 获取指定窗口的设备场景
    /// </summary>
    /// <param name="hwnd">将获取其设备场景的窗口的句柄。若为0,则要获取整个屏幕的DC</param>
    /// <returns></returns>
    [DllImport("user32.dll")]
    public static extern uint GetDC(uint hwnd);

    /// <summary>
    /// 在指定的设备场景中取得一个像素的RGB值
    /// </summary>
    /// <param name="hDC">一个设备场景的句柄</param>
    /// <param name="x"></param>
    /// <param name="y"></param>
    /// <returns></returns>
    [DllImport("gdi32.dll")]
    public static extern uint GetPixel(uint hDC,uint x,uint y);

    /// <summary>
    /// 释放由调用GetDC或GetWindowDC函数获取的指定设备场景。它对类或私有设备场景无效(但这样的调用不会造成损害)
    /// </summary>
    /// <param name="hwnd">要释放的设备场景相关的窗口句柄</param>
    /// <param name="hdc">要释放的设备场景句柄</param>
    /// <returns></returns>
    [DllImport("user32.dll")]
    public static extern uint ReleaseDC(uint hwnd,uint hdc);

    /// <summary>
    /// 获取整个窗口(包括边框、滚动条、标题栏、菜单等)的设备场景
    /// </summary>
    /// <param name="hwnd">将获取其设备场景的窗口</param>
    /// <returns></returns>
    [DllImport("user32.dll")]
    public static extern uint GetWindowDC(uint hwnd);

    /// <summary>
    /// 模拟一次鼠标事件
    /// </summary>
    /// <param name="dwFlags"></param>
    /// <param name="dx"></param>
    /// <param name="dy"></param>
    [DllImport("user32.dll")]
    public static extern void mouse_event(uint dwFlags,uint dx,uint dy);

    [DllImport(
    "user32.dll")]
    public static extern void keybd_event(byte bVk, byte bScan, long dwFlags, long dwExtraInfo);

    /// <summary>
    /// 判断指定键盘状态
    /// </summary>
    /// <param name="nVirtKey"></param>
    /// <returns></returns>
    [DllImport("user32.dll",CharSet=CharSet.Auto,ExactSpelling= true)]
    public static extern short GetKeyState(long nVirtKey);
    }

    /// <summary>
    /// 初始化色板颜色-白色
    /// </summary>
    private void InitPanelColor()
    {
    panelColor.BackColor
    = Color.FromArgb(Convert.ToInt32(txtRedValue.Text), Convert.ToInt32(txtGreenValue.Text), Convert.ToInt32(txtBlueValue.Text));
    }

    private void txtRedValue_TextChanged(object sender, EventArgs e)
    {
    redValue
    = Convert.ToInt32(txtRedValue.Text == "" ? "0" : txtRedValue.Text);
    SetPanelColor();
    }

    private void txtGreenValue_TextChanged(object sender, EventArgs e)
    {
    greenValue
    = Convert.ToInt32(txtGreenValue.Text == "" ? "0" : txtGreenValue.Text);
    SetPanelColor();
    }

    private void txtBlueValue_TextChanged(object sender, EventArgs e)
    {
    blueValue
    = Convert.ToInt32(txtBlueValue.Text == "" ? "0" : txtBlueValue.Text);
    SetPanelColor();
    }

    /// <summary>
    /// 设置面板颜色
    /// </summary>
    private void SetPanelColor()
    {
    panelColor.BackColor
    = Color.FromArgb(LimitNum(redValue), LimitNum(greenValue), LimitNum(blueValue));
    }

    private int LimitNum(int num)
    {
    if (num > 255)
    {
    return 255;
    }
    else if (num < 0)
    {
    return 0;
    }
    else
    {
    return num;
    }
    }

    private void panelColor_MouseClick(object sender, MouseEventArgs e)
    {
    flag
    = true;
    }

    private void colorForm_MouseMove(object sender, MouseEventArgs e)
    {
    isGetColor();
    }

    /// <summary>
    /// 按ESC开始停止取色
    /// </summary>
    private void isGetColor()
    {
    if (((ushort)WinInfo.GetKeyState(27) & 0xffff) != 0)
    {
    flag
    = true;
    }
    else
    {
    flag
    = false;
    this.Cursor = Cursors.Arrow;
    }

    if (flag)
    {
    this.Cursor = Cursors.Hand;
    POINTAPI Papi
    = new POINTAPI();
    WinInfo.GetCursorPos(
    ref Papi);
    uint v_hwnd = WinInfo.WindowFromPoint(Papi.x, Papi.y);
    uint v_DC = WinInfo.GetDC(v_hwnd);
    WinInfo.ScreenToClient(v_hwnd,
    ref Papi);
    WinInfo.mouse_event(
    0x0002, Papi.x, Papi.y);
    uint v_Color = WinInfo.GetPixel(v_DC, Papi.x, Papi.y);

    uint v_Red, v_Green, v_Blue;
    v_Red
    = v_Color & 0xff;
    v_Green
    = (v_Color & 0xff00) / 256;
    v_Blue
    = (v_Color & 0xff0000) / 65536;

    this.txtColorValue.Text = "#" + v_Red.ToString("x").PadLeft(2, '0') + v_Green.ToString("x").PadLeft(2, '0') + v_Blue.ToString("x").PadLeft(2, '0');
    txtRedValue.Text
    = v_Red.ToString("d");
    txtGreenValue.Text
    = v_Green.ToString("d");
    txtBlueValue.Text
    = v_Blue.ToString("d");
    this.panelColor.BackColor = Color.FromArgb((int)v_Red, (int)v_Green, (int)v_Blue);
    WinInfo.ReleaseDC(v_hwnd, v_DC);
    }
    }

    private void txtRedValue_KeyPress(object sender, KeyPressEventArgs e)
    {
    if (e.KeyChar != 8 && !char.IsDigit(e.KeyChar))
    {
    e.Handled
    = true;
    }
    }

    private void txtGreenValue_KeyPress(object sender, KeyPressEventArgs e)
    {
    if (e.KeyChar != 8 && !char.IsDigit(e.KeyChar))
    {
    e.Handled
    = true;
    }
    }

    private void txtBlueValue_KeyPress(object sender, KeyPressEventArgs e)
    {
    if (e.KeyChar != 8 && !char.IsDigit(e.KeyChar))
    {
    e.Handled
    = true;
    }
    }

    private void 关于ToolStripMenuItem_Click(object sender, EventArgs e)
    {
    MessageBox.Show(
    "winform版取色器\r\r版本1.0.0\r\r作者 忧忧夏天", "关于", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
    }

    private void 介绍ToolStripMenuItem_Click(object sender, EventArgs e)
    {
    MessageBox.Show(
    "在颜色表里面按ESC开取色,要结束再按一次ESC\r\r交流QQ466260359", "介绍", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
    }

    }
    }

    源码下载

  • 相关阅读:
    进程池线程池
    线程与其操作方法
    生产者消费者模型
    Java反射机制详解
    ajax跨域原理以及解决方案
    数据库连接池的选择 Druid
    新目标
    让webstorm支持avalon语法自动补全
    使用IDEA和gradle搭建Spring MVC和MyBatis开发环境
    使用IDEA自带的rest client参数传递乱码问题
  • 原文地址:https://www.cnblogs.com/xqhppt/p/1898435.html
Copyright © 2020-2023  润新知