Windows核心北京賽車遊戲一條龍服務編程_獲取鼠標指定位置的RGB顏色值
Windows核心北京賽車遊戲一條龍服務【大神源碼論壇】dsluntan.com 【布丁源碼論壇】budingbbs.com 企娥3393756370編程_獲取鼠標指定位置的RGB顏色值
大家平常會見到很多屏幕取色工具,其原理都是獲取鼠標位置的屏幕像素點顏色!
一般思路都是:獲取鼠標位置,然後取出鼠標指向的屏幕像素點顏色!
GetCursorPos函數是WindowsSDK庫下的一個API函數,用於獲取鼠標位於屏幕中偏移的坐標信息!
函數原型:
[cpp] view plain copy- BOOL GetCursorPos(LPPOINT lpPoint);
- 參數介紹:LPPOINT lpPoint:用於接受鼠標坐標的POINT結構體指針
- 返回值:成功返回TRUE,失敗返回FALSE!
示例:
[cpp] view plain copy
- 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繪圖設備描述符!
函數原型:
[cpp] view plain copy- HDC GetDC(HWND hWnd);
- 參數介紹:HWND hWnd: 窗口句柄,NULL獲取屏幕的DC句柄
- 返回值:窗口DC,否則返回NULL
有了窗體的繪圖信息,那麽怎麽得到DC指向的繪圖表裏的繪圖信息呢?
GetPixel 此函數是用來獲取指定DC繪圖表裏的像素點
函數原型:
[cpp] view plain copy- COLORREF GetPixel(HDC hdc, int nXPos, int nYPos);
- 參數介紹:
- HDC hdc:DC
- int nXPos:X坐標
- int nYPos:Y坐標
- 返回值:返回DC下的RGB顏色值,註意這個值是RGB三種色組合起來的值,在讀取時需要分解!
示例:
[cpp] view plain copy- 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);
運行結果:
完整代碼:
[cpp] view plain copy- 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值分解代碼
[cpp] view plain copy- 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,然後在用賦值運算符獲得位!
[cpp] view plain copy- WORD r = (Windows_Hdc_RGB & 0x00FF0000) >> 16;
以此類推,下面兩個就較為容易理解了,加上括號只是考慮到優先級的問題!
[cpp] view plain copy- WORD g = (Windows_Hdc_RGB & 0x0000FF00) >> 8;
- WORD b = Windows_Hdc_RGB & 0x000000FF;
其實也可以使用更加簡單的方法,就是調用Windows宏函數:GetRValue、GetGValue、GetBValue
[cpp] view plain copy- 示例:
- 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
不過我們在內存中讀取的時候也要考慮一下大小端的問題!
Windows核心北京賽車遊戲一條龍服務編程_獲取鼠標指定位置的RGB顏色值