1. 程式人生 > >C++桌面截圖

C++桌面截圖

ScreenShot.h

#include <atlimage.h>
void ScreenShot(LPCTSTR s);

ScreenShot.cpp

#include "ScreenShot.h"
#include <atlimage.h>
void ScreenShot(LPCTSTR s)
{
    HDC hdcSrc = GetDC(NULL);
    int nBitPerPixel = GetDeviceCaps(hdcSrc, BITSPIXEL);
    int nWidth = GetDeviceCaps(hdcSrc, HORZRES);
    int
nHeight = GetDeviceCaps(hdcSrc, VERTRES); CImage image; image.Create(nWidth, nHeight, nBitPerPixel); BitBlt(image.GetDC(), 0, 0, nWidth, nHeight, hdcSrc, 0, 0, SRCCOPY); ReleaseDC(NULL, hdcSrc); image.ReleaseDC(); image.Save(s, Gdiplus::ImageFormatPNG);//ImageFormatJPEG }

呼叫

    const
char *str = "D:\\test11.bmp";//多位元組字符集可以這麼做,如果是Unicode編碼,則需要轉換成CString後賦值給LPCTSTR ScreenShot((LPCTSTR)(CString)str); ScreenShot(str);

還有一點注意的是,如果在win10裡設定了縮放,比如縮放125%,那麼擷取的就不是完整的螢幕了。因為GetDeviceCaps返回的是除以125%的結果,1920變成了1536。解決方法目前只有手動指定bitmap的大小了.


第二種方法

#include <windows.h>
HBITMAP CopyScreenToBitmap(LPRECT lpRect)
{

    HDC   hScrDC, hMemDC;
    //   螢幕和記憶體裝置描述表   
HBITMAP hBitmap, hOldBitmap; // 點陣圖控制代碼 int nX, nY, nX2, nY2; // 選定區域座標 int nWidth, nHeight; // 點陣圖寬度和高度 int xScrn, yScrn; // 螢幕解析度 // 確保選定區域不為空矩形 if (IsRectEmpty(lpRect)) return NULL; //為螢幕建立裝置描述表 hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL); //為螢幕裝置描述表建立相容的記憶體裝置描述表 hMemDC = CreateCompatibleDC(hScrDC); // 獲得選定區域座標 nX = lpRect->left; nY = lpRect->top; nX2 = lpRect->right; nY2 = lpRect->bottom; // 獲得螢幕解析度 xScrn = GetDeviceCaps(hScrDC, HORZRES); yScrn = GetDeviceCaps(hScrDC, VERTRES); //確保選定區域是可見的 if (nX < 0) nX = 0; if (nY < 0) nY = 0; if (nX2 > xScrn) nX2 = xScrn; if (nY2 > yScrn) nY2 = yScrn; nWidth = nX2 - nX; nHeight = nY2 - nY; // 建立一個與螢幕裝置描述表相容的點陣圖 hBitmap = CreateCompatibleBitmap(hScrDC, nWidth, nHeight); // hBitmap = (HBITMAP)LoadImage(NULL, ".//MyData//SnapStill.bmp", IMAGE_BITMAP, // 0, 0, LR_CREATEDIBSECTION|LR_DEFAULTSIZE|LR_LOADFROMFILE); // 把新點陣圖選到記憶體裝置描述表中 hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap); // 把螢幕裝置描述表拷貝到記憶體裝置描述表中 BitBlt(hMemDC, 0, 0, nWidth, nHeight, hScrDC, nX, nY, SRCCOPY); //得到螢幕點陣圖的控制代碼 hBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap); //清除 DeleteDC(hScrDC); DeleteDC(hMemDC); // 返回點陣圖控制代碼 return hBitmap; } BOOL SaveToFile(HBITMAP hBitmap, LPCTSTR lpszFileName) { HDC hDC; //當前解析度下每象素所佔位元組數 int iBits; //點陣圖中每象素所佔位元組數 WORD wBitCount; //定義調色盤大小, 點陣圖中畫素位元組大小 ,點陣圖檔案大小 , 寫入檔案位元組數 DWORD dwPaletteSize = 0, dwBmBitsSize = 0, dwDIBSize = 0, dwWritten = 0; //點陣圖屬性結構 BITMAP Bitmap; //點陣圖檔案頭結構 BITMAPFILEHEADER bmfHdr; //點陣圖資訊頭結構 BITMAPINFOHEADER bi; //指向點陣圖資訊頭結構 LPBITMAPINFOHEADER lpbi; //定義檔案,分配記憶體控制代碼,調色盤控制代碼 HANDLE fh, hDib, hPal, hOldPal = NULL; //計算點陣圖檔案每個畫素所佔位元組數 hDC = CreateDC("DISPLAY", NULL, NULL, NULL); iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES); DeleteDC(hDC); if (iBits <= 1) wBitCount = 1; else if (iBits <= 4) wBitCount = 4; else if (iBits <= 8) wBitCount = 8; else wBitCount = 24; GetObject(hBitmap, sizeof(Bitmap), (LPSTR)&Bitmap); bi.biSize = sizeof(BITMAPINFOHEADER); bi.biWidth = Bitmap.bmWidth; bi.biHeight = Bitmap.bmHeight; bi.biPlanes = 1; bi.biBitCount = wBitCount; bi.biCompression = BI_RGB; bi.biSizeImage = 0; bi.biXPelsPerMeter = 0; bi.biYPelsPerMeter = 0; bi.biClrImportant = 0; bi.biClrUsed = 0; dwBmBitsSize = ((Bitmap.bmWidth * wBitCount + 31) / 32) * 4 * Bitmap.bmHeight; //為點陣圖內容分配記憶體 hDib = GlobalAlloc(GHND, dwBmBitsSize + dwPaletteSize + sizeof(BITMAPINFOHEADER)); lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib); *lpbi = bi; // 處理調色盤 hPal = GetStockObject(DEFAULT_PALETTE); if (hPal) { hDC = GetDC(NULL); hOldPal = SelectPalette(hDC, (HPALETTE)hPal, FALSE); RealizePalette(hDC); } // 獲取該調色盤下新的畫素值 GetDIBits(hDC, hBitmap, 0, (UINT)Bitmap.bmHeight, (LPSTR)lpbi + sizeof(BITMAPINFOHEADER) + dwPaletteSize, (BITMAPINFO *)lpbi, DIB_RGB_COLORS); //恢復調色盤 if (hOldPal) { SelectPalette(hDC, (HPALETTE)hOldPal, TRUE); RealizePalette(hDC); ReleaseDC(NULL, hDC); } //建立點陣圖檔案 fh = CreateFile(lpszFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); if (fh == INVALID_HANDLE_VALUE) return FALSE; // 設定點陣圖檔案頭 bmfHdr.bfType = 0x4D42; // "BM" dwDIBSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwPaletteSize + dwBmBitsSize; bmfHdr.bfSize = dwDIBSize; bmfHdr.bfReserved1 = 0; bmfHdr.bfReserved2 = 0; bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER) + dwPaletteSize; // 寫入點陣圖檔案頭 WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL); // 寫入點陣圖檔案其餘內容 WriteFile(fh, (LPSTR)lpbi, dwDIBSize, &dwWritten, NULL); //清除 GlobalUnlock(hDib); GlobalFree(hDib); CloseHandle(fh); return TRUE; } int main() { //HDC fullScreen = GetDC(NULL); HDC hdc = GetDC(NULL); RECT rect = { 0, 0, GetDeviceCaps(hdc, HORZRES), GetDeviceCaps(hdc, VERTRES) }; SaveToFile(CopyScreenToBitmap(&rect), "c:\\users\\asus\\desktop\\a.bmp"); return 0; }