以前本人用C#制作過一些小游戲的外掛,其中一步最重要的原理是截取電腦的屏幕,然后分析關鍵像素點的信息。現在用C++重用這些程序時,在截屏上遇到一些問題,現在終於解決了,貼出自己整理后的代碼。
分為win32代碼和MFC代碼,如下
1 void Test_captrueScreenwin32() 2 { 3 HDC hDesktopDc=CreateDC(_T("DISPLAY"), NULL, NULL, NULL); 4 int width=GetDeviceCaps(hDesktopDc,HORZRES); 5 int height=GetDeviceCaps(hDesktopDc,VERTRES); 6 7 HBITMAP hMemBmp; 8 HDC hMemDc; 9 hMemBmp= CreateCompatibleBitmap(hDesktopDc,width,height); 10 hMemDc=CreateCompatibleDC(hDesktopDc); 11 ::SelectObject(hMemDc,hMemBmp); 12 13 BitBlt(hMemDc,0,0,width,height,hDesktopDc,0,0,SRCCOPY); //一定得先復制到內存中去 14 15 BITMAP bmp; 16 ::GetObject(hMemBmp,sizeof(bmp),&bmp); //從HBITMAP 到BITMAP 17 18 BITMAPINFOHEADER m_bihScreen; 19 ZeroMemory(&m_bihScreen, sizeof(BITMAPINFOHEADER));//位圖信息頭 20 m_bihScreen.biBitCount = bmp.bmBitsPixel;//每個像素字節大小 21 m_bihScreen.biCompression = BI_RGB; 22 m_bihScreen.biHeight = bmp.bmHeight;//高度 23 m_bihScreen.biPlanes = 1; 24 m_bihScreen.biSize = sizeof(BITMAPINFOHEADER); 25 m_bihScreen.biSizeImage = bmp.bmWidthBytes * bmp.bmHeight;//圖像數據大小 26 m_bihScreen.biWidth = bmp.bmWidth;//寬度 27 28 byte *m_pbmScreenData = new byte[bmp.bmWidthBytes * bmp.bmHeight]; 29 GetDIBits(hMemDc,hMemBmp, 0, height, m_pbmScreenData, 30 (LPBITMAPINFO) &m_bihScreen, DIB_RGB_COLORS);//獲取位圖數據 從BITMAP到內存數據 31 32 TwoDimesionArray<RGBQUAD> colors(width,height); 33 for (int j=0;j<height;++j) 34 { 35 for (int i=0;i<width;++i) 36 { 37 byte *p=m_pbmScreenData+(height-1-j)*bmp.bmWidthBytes+i*4; 38 RGBQUAD c={int(*p),int(*(p+1)),int(*(p+2))}; //這里獲取每個位置上的像素 39 colors.SetValue(i,j,c); 40 } 41 } 42 43 ImageIO writer; 44 writer.WriteBmp(colors,"D:\\z.bmp"); 45 }
1 void Test_captureScreenMFC() 2 { 3 CDC *pDesktopDC = CDC::FromHandle(::GetDC(NULL));//獲取當前整個屏幕DC 4 int width = pDesktopDC->GetDeviceCaps(HORZRES); 5 int height = pDesktopDC->GetDeviceCaps(VERTRES); 6 7 CBitmap memBmp; 8 CDC memDC; 9 memBmp.CreateCompatibleBitmap(pDesktopDC, width, height); 10 memDC.CreateCompatibleDC(pDesktopDC); 11 memDC.SelectObject(&memBmp); //將memBitmap選入內存DC 12 13 memDC.BitBlt(0, 0, width, height, pDesktopDC, 0, 0, SRCCOPY);//復制屏幕圖像到內存DC 14 15 BITMAP bmp; 16 memBmp.GetBitmap(&bmp); //CBitmap到BITMAP 17 18 BITMAPINFOHEADER m_bihScreen; 19 ZeroMemory(&m_bihScreen, sizeof(BITMAPINFOHEADER));//位圖信息頭 20 m_bihScreen.biBitCount = bmp.bmBitsPixel;//每個像素字節大小 21 m_bihScreen.biCompression = BI_RGB; 22 m_bihScreen.biHeight = bmp.bmHeight;//高度 23 m_bihScreen.biPlanes = 1; 24 m_bihScreen.biSize = sizeof(BITMAPINFOHEADER); 25 m_bihScreen.biSizeImage = bmp.bmWidthBytes * bmp.bmHeight;//圖像數據大小 26 m_bihScreen.biWidth = bmp.bmWidth;//寬度 27 28 byte *m_pbmScreenData = new byte[bmp.bmWidthBytes * bmp.bmHeight]; 29 GetDIBits(/*pDesktopDC->m_hDC*/memDC.m_hDC, (HBITMAP)memBmp.m_hObject, 0, height, m_pbmScreenData, 30 (LPBITMAPINFO) &m_bihScreen, DIB_RGB_COLORS);//獲取位圖數據 從BITMAP到內存數據 31 32 TwoDimesionArray<RGBQUAD> colors(width,height); 33 for (int j=0;j<height;++j) 34 { 35 for (int i=0;i<width;++i) 36 { 37 byte *p=m_pbmScreenData+(height-1-j)*bmp.bmWidthBytes+i*4; 38 RGBQUAD c={int(*p),int(*(p+1)),int(*(p+2))}; 39 colors.SetValue(i,j,c); 40 } 41 } 42 43 ImageIO writer; 44 writer.WriteBmp(colors,"D:\\z.bmp"); 45 }
GetDIBits是DDB轉化為DIB的關鍵函數。
TwoDimesionArray<T>是自定義的模板類,封裝了二維數組的相關操作。
ImageIO 是保存圖片到文件的類。
通過這兩段代碼顯示了win32和MFC對應數據類型的不同