Windows核心编程_获取鼠标指定位置的RGB颜色值
大家平常会见到很多屏幕取色工具,其原理都是获取鼠标位置的屏幕像素点颜色!
一般思路都是:获取鼠标位置,然后取出鼠标指向的屏幕像素点颜色!
GetCursorPos函数是WindowsSDK库下的一个API函数,用于获取鼠标位于屏幕中偏移的坐标信息!
函数原型:
BOOL GetCursorPos(LPPOINT lpPoint);
参数介绍:LPPOINT lpPoint:用于接受鼠标坐标的POINT结构体指针
返回值:成功返回TRUE,失败返回FALSE!
示例:
POINT Mouse_X_Y; //存放鼠标坐标结构体
if (FALSE == GetCursorPos(&Mouse_X_Y)){ //获取鼠标坐标
printf("error:无法获取鼠标指针位于屏幕的坐标值");
}
printf("鼠标的X坐标:%d,鼠标的Y坐标:%d", Mouse_X_Y.x, Mouse_X_Y.y);
getchar();
运行结果:
已经可以成功知道鼠标的坐标了,那么接下来就是获取鼠标指向屏幕上的像素点信息!
首先Windows下一个窗口的绘图信息(像素点信息)都是由DC来描述的,DC指向一个绘图设备表,这个表里包含了一个窗口的所有绘图信息,比如位于屏幕上的坐标,还有坐标上的像素点信息等等!
而且我们的窗口是显示在屏幕上的,所以我们如果想取某个窗口的颜色,可以把窗口放到屏幕上,Windows会把窗口的绘图信息,呈现到屏幕的DC中去!
GetDC,可以用来获取指定程序的DC绘图设备描述符!
函数原型:
HDC GetDC(HWND hWnd);
参数介绍:HWND hWnd: 窗口句柄,NULL获取屏幕的DC句柄
返回值:窗口DC,否则返回NULL
有了窗体的绘图信息,那么怎么得到DC指向的绘图表里的绘图信息呢?
GetPixel 此函数是用来获取指定DC绘图表里的像素点
函数原型:
COLORREF GetPixel(HDC hdc, int nXPos, int nYPos);
参数介绍:
HDC hdc:DC
int nXPos:X坐标
int nYPos:Y坐标
返回值:返回DC下的RGB颜色值,注意这个值是RGB三种色组合起来的值,在读取时需要分解!
示例:
HDC hdc = GetDC(NULL);
COLORREF Windows_Hdc_RGB = GetPixel(hdc, Mouse_X_Y.x, Mouse_X_Y.y); //获取指定DC上的像素点RGB值
//获取RGB,其可以使用:GetRValue,GetGvalue,GetBvalue函数代替
WORD r = (Windows_Hdc_RGB & 0x00FF0000) >> 16;
WORD g = (Windows_Hdc_RGB & 0x0000FF00) >> 8;
WORD b = Windows_Hdc_RGB & 0x000000FF;
printf("鼠标位置的颜色RGB值是:%d,%d,%d", r, g, b);
运行结果:
完整代码:
POINT Mouse_X_Y; //存放鼠标坐标结构体
if (FALSE == GetCursorPos(&Mouse_X_Y)){ //获取鼠标坐标
printf("error:无法获取鼠标指针位于屏幕的坐标值");
}
printf("鼠标的X坐标:%d,鼠标的Y坐标:%d\n", Mouse_X_Y.x, Mouse_X_Y.y);
HDC hdc = GetDC(NULL);
COLORREF Windows_Hdc_RGB = GetPixel(hdc, Mouse_X_Y.x, Mouse_X_Y.y); //获取指定DC上的像素点RGB值
//获取RGB,其可以使用:GetRValue,GetGvalue,GetBvalue函数代替
WORD r = (Windows_Hdc_RGB & 0x00FF0000) >> 16;
WORD g = (Windows_Hdc_RGB & 0x0000FF00) >> 8;
WORD b = Windows_Hdc_RGB & 0x000000FF;
printf("鼠标位置的颜色RGB值是:%d,%d,%d", r, g, b);
getchar();
这里来说一下这三行RGB值分解代码
WORD r = (Windows_Hdc_RGB & 0x00FF0000) >> 16;
WORD g = (Windows_Hdc_RGB & 0x0000FF00) >> 8;
WORD b = Windows_Hdc_RGB & 0x000000FF;
GetPixel函数返回的是DC下像素点RGB值,也就是(255,255,255)组合的十六进制值就是:0xFFFFFF(十进制的255对应0xFF十六进制),1个字节最大范围能表示255,所以我们要分别取RGB每个值就将返回的值拆分成3个字节来处理!
比如指定像素点下RGB值是137,47,66,那么137会放在高位,47会放在中位,66会放在低位用四个字节来存储它们,但是如果你直接打印的话,就是4个字节表示的值,并非1374766,
比如一个四字节的存储空间,BIT位就是:00000000 00000000 0000000 00000000
那么第三个字节用于存储R,倒数第二个字节用于存储G,最后一个用于存储B
但是如果你直接打印的话并非每个字节表示的数加在一起的,而是所有字节的BIT位按次方运算出来的结果!
计算机内部本身是没有加减乘除的,只有通过位移BIT位和次方运算得出结果!
那么如果我们要取R的值,需要先进行与运算
COLORREF原型是WORD,而WORD占4字节,0XFF表示一个字节(bit:11111111),所以我们先用与运算将Windows_Hdc_RGB里的BIT位于0x00FF0000进行运算:0x00FF0000=00000000 11111111 00000000 00000000
与运算是将两个数bit位上相同的值保留,所以这里我们只保留了第三个字节上的位数,其余的全部置0!
比如Windows_Hdc_RGB上的值是:00000000 01010000 10010100 00000001
那么经过与运算之后就为:
00000000 01010000 00000000 00000000
这里还不能直接用赋值的方式接受它的值,因为直接进行与运算的话仅仅是改变的BIT位,但是返回只会返回最低位一组bit位,所以我们要将bit位右移16位放到低位!
00000000 01010000 0000000 00000000 >> 16
00000000 00000000 0000000 01010000,然后在用赋值运算符获得位!
WORD r = (Windows_Hdc_RGB & 0x00FF0000) >> 16;
以此类推,下面两个就较为容易理解了,加上括号只是考虑到优先级的问题!
WORD g = (Windows_Hdc_RGB & 0x0000FF00) >> 8;
WORD b = Windows_Hdc_RGB & 0x000000FF;
其实也可以使用更加简单的方法,就是调用Windows宏函数:GetRValue、GetGValue、GetBValue
示例:
WORD r = GetRValue(Windows_Hdc_RGB);
WORD g = GetGValue(Windows_Hdc_RGB);
WORD b = GetBValue(Windows_Hdc_RGB);
我们按下F12看声明与定义可以看到其内部实现和我们上面用的方法一致:
LOBYTE宏函数:
不过可以看到它是以BGR顺序来读取的,但是GetPixel是以RGB顺序保存的,所以建议使用上面的方法,不然可能会导致获取到的颜色表示顺序错乱掉,但是也可以把宏函数的调用顺序改一下就可以了!
这里在说说一般像素点的存储都是:
00000000 00000000 00000000 00000000 = AAAAAAAA RRRRRRRR GGGGGGGG BBBBBBBB
A=透明度
R=红色
G=黄色
V=蓝色
RGB556格式:RRRRR000 GGGGG000 BBBBBB00
RGB555格式:RRRRR000 GGGGG000 BBBBB000
不过我们在内存中读取的时候也要考虑一下大小端的问题!
相关资料:图像理论知识