GDI方式截取系统屏幕

这段代码展示了如何利用GDI(图形设备接口)在Windows系统中捕获屏幕截图并保存为位图文件。通过创建设备上下文,获取屏幕尺寸,创建兼容位图,进行位块传送(BitBlt),实现屏幕内容的复制。最后将位图数据写入到.bmp文件中。
摘要由CSDN通过智能技术生成
#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 ;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值