VC螢幕截圖,儲存為Bmp檔案
阿新 • • 發佈:2018-12-31
新建一個MFC基於對話方塊的應用程式,在介面上放一個Button,為其實現點選事件,程式碼如下:
void CScreenShotDlg::OnBtnScreenshot()
{
RECT rect = {0, 0, 1900, 1000};
HBITMAP hbmp = CopyScreenToBitmap(&rect);
SaveBitmapToFile(hbmp, "a.bmp");
MessageBox("Save bmp file Successful");
}
被呼叫的這兩個函式實現如下:
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); // 建立一個與螢幕裝置描述表相容的點陣圖 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; } /* lpFileName: 點陣圖檔名 */ BOOL SaveBitmapToFile(HBITMAP hBitmap, LPSTR lpFileName) { HDC hDC; // 裝置描述表 int iBits; // 當前顯示解析度下每個畫素所佔位元組數 WORD wBitCount; // 點陣圖中每個畫素所佔位元組數 DWORD dwPaletteSize = 0, dwBmBitsSize, dwDIBSize, dwWritten; // 調色盤大小,點陣圖資料大小,點陣圖檔案大小,寫入檔案位元組數 BITMAP Bitmap; //點陣圖屬性結構 BITMAPFILEHEADER bmfHdr; // 點陣圖檔案頭 BITMAPINFOHEADER bi; // 點陣圖資訊頭 LPBITMAPINFOHEADER lpbi; // 指向點陣圖資訊頭結構 HANDLE fh, hDib; // 定義檔案,分配記憶體控制代碼 HPALETTE 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 if (iBits <= 24) wBitCount = 24; else wBitCount = 32; if (wBitCount <= 8) dwPaletteSize = (1 << wBitCount) * sizeof(RGBQUAD); // 計算調色盤大小 // 設定點陣圖資訊頭結構 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.biClrUsed = 0; bi.biClrImportant = 0; dwBmBitsSize = ((Bitmap.bmWidth * wBitCount + 31) / 32) * 4 * Bitmap.bmHeight; hDib = GlobalAlloc(GHND, dwBmBitsSize + dwPaletteSize + sizeof(BITMAPINFOHEADER)); // 為點陣圖內容分配記憶體 lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib); *lpbi = bi; // 處理調色盤 hPal = (HPALETTE)GetStockObject(DEFAULT_PALETTE); if (hPal) { hDC = GetDC(NULL); hOldPal = SelectPalette(hDC, 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, hOldPal, TRUE); RealizePalette(hDC); ReleaseDC(NULL, hDC); } // 建立點陣圖檔案 fh = CreateFile(lpFileName, 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; }