屏幕抓取程序的意思是將整個屏幕圖顯示在應用程序的用戶區中,等價于截圖。
對桌面窗口的操作:
首先得知道桌面窗口的寬和高,獲取寬和高需要利用窗口的設備句柄,而獲取設備句柄需要知道窗口句柄,這一系列的連串關系如下:
窗口句柄——>設備句柄——>獲取設備句柄屬性(比如寬和高)。(書本采用的一種方法,但至少也把這種種被需要的關系復習了一下,必須承認,初學需要重復很多次才能形成熟練意識)
hwndDeskTop = GetDesktopWindow();
// 獲取桌面窗口的窗口句柄
hdcDeskTop = GetDC(hwndDeskTop);
// 創建基本桌面窗口的設備描述表 這里借用兩個函數,另外還有一種方法,直接創建一個桌面窗口設備的DC
hdcDeskTop = CreateDC(
"DISPLAY",NULL,NULL,NULL);
//CreateDC()獲得整個屏幕的DC,一步到位 有了句柄之后,就可以獲得(或設置)這個DC的各種屬性,比如,有多寬,多高等等....通過函數GetDeviceCaps()實現。摘抄函數原型如下:
int GetDeviceCaps(HDC hdc; //設備DCint nIndex;
//返回的索引項
);
設備DC的信息很多,因此,nIndex的項尤其多。在這個例子只需要得到屏幕的寬和高。
cxScreen = GetDeviceCaps(hdcDeskTop, HORZRES);
// 獲取桌面窗口的大小,也相當于矩形右下角的x,y坐標
cyScreen = GetDeviceCaps(hdcDeskTop, VERTRES);
?
接下來的這套流程比較繁雜,但是用最簡易的方式描述,得到屏幕DC之后,再創建一個兼容DC(兼容屏幕設備),和一個兼容位圖(兼容屏幕),將兼容位圖放置在兼容DC中,準備用它來存放屏幕的位圖。可以通俗的理解為是一個容器么?兼容DC容納兼容位圖。
hdcMem = CreateCompatibleDC(hdcDeskTop);
// 創建與顯示設備描述表兼容的內存設備描述表
hBitmap =
CreateCompatibleBitmap( hdcDeskTop, cxScreen, cyScreen);
SelectObject(hdcMem, hBitmap);//并選入內存設備描述表 設備已經就緒,最后將屏幕的位圖移動到兼容DC中的兼容位圖上。
BitBlt(hdcMem,
0,
0, cxScreen, cyScreen,hdcDeskTop,
0,
0 ,SRCCOPY);
再看來BitBlt()函數,摘抄如下:
BOOL BitBlt(
HDC hDCDest,//目標設備描述表
int nXDest,
//目標矩形左上角x坐標
int nYDest,
//目標矩形左上角y坐標
int nWidth,
//目標矩形寬
int nHeight,
//目標矩形高
HDC hDCSrc,
//源設備描述表
int nXDSrc,
//源矩形x坐標(左上角)
int nYDSrc,
//源矩形y坐標
DWORD dwRop
//執行的光柵操作
);
其中最后一條DWORD dwRop光柵操作,讓我聯想起C語言的圖形復制,就是在復制的過程中,如何與目標進行某種混合操作,比如讓它反色(黑變白,白變黑),OR,異或操作等等,大概就是這個意思。
兼容內存設備描述表——>應用程序設備描述表
內存設備描述表的工作已經完成,接著,再把這個內存設備描述表中的位圖復制到當前應用程序的用戶區中,并讓它顯示。
即:兼容內存描述表——>應用程序設備描述表。
書本在這里考慮這樣一個問題,讓位圖適當縮放來適應用戶區的大小,于是采用了另一種復制函數StretchBlt。它的參數與BitBlt大部分相似,省略。
但是,在縮放之前,又設置了一個縮放模式,通過函數SetStretchBltMode實現,摘抄如下:
int SetStretchBltMode(
HDC hDC,
int iStretchMode
);
//iStretchMode的選項
BLACKONWHITE;
//保留黑色像素,清除白色像素,一般用于單色位圖中
COLORONCOLOR;
//一般用于彩色位圖中保留位圖的顏色
WHITEONBLACK;
//保留白色像素,清除黑色像素
HALFTONE;
//對源圖像進行復雜處理,慢但是得到高質量的圖像 參數可以任意試驗,明顯HALFTONE參數截出的圖清晰很多。
通過這一系列移來移去的復制操作完成了屏幕截圖的工作,涉及一系列的位圖函數,因此有必要認真總結一下。
/*---------------桌面截圖程序研究版-----------------*/#include <windows.h>
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine,
int iCmdShow)
{static TCHAR szAppName[] = TEXT (
"HelloWin") ;HWND hwnd ; MSG msg ; WNDCLASS wndclass ; wndclass.style = CS_HREDRAW |
CS_VREDRAW ;wndclass.lpfnWndProc =
WndProc ;wndclass.cbClsExtra =
0 ;wndclass.cbWndExtra =
0 ;wndclass.hInstance =
hInstance ;wndclass.hIcon =
LoadIcon (NULL, IDI_APPLICATION) ;wndclass.hCursor =
LoadCursor (NULL, IDC_ARROW) ;wndclass.hbrBackground =
(HBRUSH) GetStockObject (WHITE_BRUSH) ;wndclass.lpszMenuName =
NULL ;wndclass.lpszClassName =
szAppName ;if (!RegisterClass (&
wndclass)){return 0 ;}hwnd =
CreateWindow (szAppName, TEXT ("鼠標消息"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL) ; ShowWindow (hwnd, iCmdShow) ; UpdateWindow (hwnd) ; while (GetMessage (&msg, NULL,
0,
0)) {TranslateMessage (&
msg) ; DispatchMessage (&
msg) ; }return msg.wParam ;
}LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{static HDC hdc,hdcDeskTop,hdcMem;PAINTSTRUCT ps ;static int cxScreen,cyScreen,cxClient,cyClient;HBITMAP hBitmap;switch (message){ case WM_CREATE://hwndDeskTop = GetDesktopWindow();// 獲取桌面窗口的窗口句柄 //hdcDeskTop = GetDC(hwndDeskTop);// 創建基本桌面窗口的設備描述表
hdcDeskTop = CreateDC(
"DISPLAY",NULL,NULL,NULL);
//CreateDC()獲得整個屏幕的DC,一步到位hdcMem = CreateCompatibleDC(hdcDeskTop);
// 創建兼容內存設備描述表
cxScreen = GetDeviceCaps(hdcDeskTop, HORZRES);
// 獲取桌面窗口的大小cyScreen =
GetDeviceCaps(hdcDeskTop, VERTRES);hBitmap = CreateCompatibleBitmap( hdcDeskTop, cxScreen, cyScreen);
// 創建兼容位圖 SelectObject(hdcMem, hBitmap);
//選入內存設備描述表//ShowWindow(hwnd, SW_HIDE);//先隱藏窗口,有這個必要嗎?此時窗口未出現
BitBlt(hdcMem, 0,
0, cxScreen, cyScreen,hdcDeskTop,
0,
0 ,SRCCOPY);
// 將桌面位圖的像素傳送到兼容位圖上 //Sleep(1000);//ShowWindow(hwnd, SW_SHOW);//顯示窗口
DeleteDC(hdcDeskTop);return 0 ;case WM_SIZE:cxClient =
LOWORD(lParam);cyClient =
HIWORD(lParam);return 0;case WM_PAINT:hdc = BeginPaint (hwnd, &
ps) ;// 將內存設備描述表的位圖壓縮顯示到程序窗口內//SetStretchBltMode(hdc, COLORONCOLOR);//iStretchMode參數任意選擇觀察//SetStretchBltMode(hdc, HALFTONE);StretchBlt(hdc,
0,
0, cxClient, cyClient, hdcMem,
0 ,
0 , cxScreen, cyScreen, SRCCOPY); EndPaint (hwnd, &
ps) ;return 0 ;case WM_DESTROY:PostQuitMessage (0) ;return 0 ;}return DefWindowProc (hwnd, message, wParam, lParam);
} ?
轉載于:https://www.cnblogs.com/tinaluo/p/5406646.html
總結
以上是生活随笔為你收集整理的屏幕抓取程序 (位图DDB的例子)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。