GDI方式截取系統屏幕

#include <iostream>
#include <windows.h>

using namespace std;

void CaptureScreenByGDI()
{
        HDC hDC = CreateDC(_T("DISPLAY"), NULL, NULL, NULL);

        int nScreenWidth = GetDeviceCaps(hDC, HORZRES);
        int nScreenHeight = GetDeviceCaps(hDC, VERTRES);

        HDC hCompatibleDC = CreateCompatibleDC(hDC);
        HBITMAP hBitmap = CreateCompatibleBitmap(hDC, nScreenWidth, nScreenHeight);

        SelectObject(hCompatibleDC, hBitmap);

        BitBlt(hCompatibleDC, 0, 0, nScreenWidth, nScreenHeight, hDC, 0, 0, SRCCOPY);

        // 獲取默認調色板
        HPALETTE hPalette = (HPALETTE)GetStockObject(DEFAULT_PALETTE);

        BITMAP bitmap;
        GetObject(hBitmap, sizeof(bitmap), (LPVOID)&bitmap);

        // 初始化位圖頭信息
        BITMAPINFOHEADER bitmapInfoHeader;
        ZeroMemory(&bitmapInfoHeader, sizeof(BITMAPINFOHEADER));

        bitmapInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
        bitmapInfoHeader.biWidth = bitmap.bmWidth;
        bitmapInfoHeader.biHeight = bitmap.bmHeight;
        bitmapInfoHeader.biPlanes = 1;
        bitmapInfoHeader.biBitCount = 24;
        bitmapInfoHeader.biCompression = BI_RGB;

        //計算信息頭及顏色表大小
        int nColors = (1 << bitmapInfoHeader.biBitCount);
        if (nColors > 256)
                nColors = 0;

        DWORD dwLength = bitmapInfoHeader.biSize + nColors * sizeof(RGBQUAD);

        HDC hTmpDC = GetDC(NULL);
        hPalette = SelectPalette(hTmpDC, hPalette, FALSE);
        RealizePalette(hTmpDC);

        // 爲信息頭和顏色表分配內存
        HANDLE hDIB = GlobalAlloc(GMEM_FIXED, dwLength);
        if (!hDIB)
        {
                SelectPalette(hTmpDC, hPalette, FALSE);
                ReleaseDC(NULL, hTmpDC);
                return ;
        }

        // 獲取位圖數據
        LPBITMAPINFOHEADER lpBitmapInfoHeader = (LPBITMAPINFOHEADER)hDIB;
        *lpBitmapInfoHeader = bitmapInfoHeader;

        // 調用GetBIDBits
        BOOL b = GetDIBits(hTmpDC, hBitmap, 0L, (DWORD)bitmapInfoHeader.biHeight, (LPBYTE)NULL, (LPBITMAPINFO)lpBitmapInfoHeader, (DWORD)DIB_RGB_COLORS);

        bitmapInfoHeader = *lpBitmapInfoHeader;

        // 圖像的每行都對齊32字節
        if (bitmapInfoHeader.biSizeImage == 0)
        {
                bitmapInfoHeader.biSizeImage = ((((bitmapInfoHeader.biWidth * bitmapInfoHeader.biBitCount) + 31) & ~31) / 8) * bitmapInfoHeader.biHeight;

                if (bitmapInfoHeader.biCompression != BI_RGB)
                        bitmapInfoHeader.biSizeImage = (bitmapInfoHeader.biSizeImage * 3) / 2;
        }

        // 重新分配內存大小
        dwLength += bitmapInfoHeader.biSizeImage;
        HANDLE hMem = NULL;
        if (hMem = GlobalReAlloc(hDIB, dwLength, GMEM_MOVEABLE))
        {
                hDIB = hMem;
        }
        else
        {
                GlobalFree(hDIB);
                SelectPalette(hTmpDC, hPalette, FALSE);
                ReleaseDC(NULL, hTmpDC);
                return ;
        }

        lpBitmapInfoHeader = (LPBITMAPINFOHEADER)hDIB;

        b = GetDIBits(hTmpDC, hBitmap, 0L, (DWORD)bitmapInfoHeader.biHeight,
                (LPBYTE)lpBitmapInfoHeader + (bitmapInfoHeader.biSize + nColors * sizeof(RGBQUAD)),
                (LPBITMAPINFO)lpBitmapInfoHeader, (DWORD)DIB_RGB_COLORS);

        if (!b)
        {
                GlobalFree(hDIB);
                SelectPalette(hTmpDC, hPalette, FALSE);
                ReleaseDC(NULL, hTmpDC);
                return ;
        }

        SelectPalette(hTmpDC, hPalette, FALSE);
        ReleaseDC(NULL, hTmpDC);

        BITMAPFILEHEADER bitmapFileHeader;
        ZeroMemory(&bitmapFileHeader, sizeof(BITMAPFILEHEADER));
        bitmapFileHeader.bfType = (DWORD)0x4D42;
        bitmapFileHeader.bfSize = 54 + bitmapInfoHeader.biSizeImage;
        bitmapFileHeader.bfOffBits = 54;

        DWORD written = 0;

        HANDLE hFile = CreateFile(_T("D:\\CaptureScreenByGDI.bmp"), GENERIC_ALL, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

        if (hFile == INVALID_HANDLE_VALUE)
        {
                return ;
        }

        b = WriteFile(hFile, &bitmapFileHeader, sizeof(BITMAPFILEHEADER), &written, NULL);
        b = WriteFile(hFile, hDIB, bitmapFileHeader.bfSize, &written, NULL);

        FlushFileBuffers(hFile);
        CloseHandle(hFile);

        return ;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章