利用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);
}

}
}

源码下载

原文地址:https://www.cnblogs.com/xqhppt/p/1898435.html