一 效果图
为了实现这个取色器,在网上查了很多关于取色器的资料,起先是通过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);
}
}
}