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