C++使用Win32GDI DC进行屏幕截图
代码
#include <windows.h>
#include <Psapi.h>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <memory>
#include <string>
#include <thread>
#include <dxgi.h>
#include <d3d11.h>
#include <wrl.h>
BOOL SaveBitmapToFile(HBITMAP hBitmap, LPCTSTR filename)
{
    BITMAP bmp;
    GetObject(hBitmap, sizeof(BITMAP), &bmp);
    DWORD dwBmpSize = ((bmp.bmWidth * bmp.bmBitsPixel + 31) / 32) * 4 * bmp.bmHeight;
    HANDLE hDIB = GlobalAlloc(GHND, dwBmpSize);
    char *lpbitmap = (char *)GlobalLock(hDIB);
    BITMAPINFOHEADER bi;
    bi.biSize = sizeof(BITMAPINFOHEADER);
    bi.biWidth = bmp.bmWidth;
    bi.biHeight = bmp.bmHeight;
    bi.biPlanes = 1;
    bi.biBitCount = 24;
    bi.biCompression = BI_RGB;
    bi.biSizeImage = 0;
    bi.biXPelsPerMeter = 0;
    bi.biYPelsPerMeter = 0;
    bi.biClrImportant = 0;
    bi.biClrUsed = 0;
    // 获取位图数据
    GetDIBits(GetDC(NULL), hBitmap, 0, (UINT)bmp.bmHeight, lpbitmap, (BITMAPINFO *)&bi, DIB_RGB_COLORS);
    // 创建文件并写入数据
    HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    DWORD dwWritten;
    BITMAPFILEHEADER bfh;
    bfh.bfType = 0x4D42; // BM
    bfh.bfSize = sizeof(BITMAPFILEHEADER) + dwBmpSize;
    bfh.bfReserved1 = 0;
    bfh.bfReserved2 = 0;
    bfh.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);
    WriteFile(hf, (LPSTR)&bfh, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
    WriteFile(hf, (LPSTR)&bi, sizeof(BITMAPINFOHEADER), &dwWritten, NULL);
    WriteFile(hf, lpbitmap, dwBmpSize, &dwWritten, NULL);
    // 清理
    GlobalUnlock(hDIB);
    GlobalFree(hDIB);
    CloseHandle(hf);
    return TRUE;
}
bool CaptureScreen(const wchar_t *filePath)
{
    // 获取屏幕宽高
    int width = GetSystemMetrics(SM_CXSCREEN);
    int height = GetSystemMetrics(SM_CYSCREEN);
    // 创建屏幕DC
    HDC hScreenDC = GetDC(NULL);
    if (!hScreenDC)
    {
        std::cerr << "Failed to get screen DC" << std::endl;
        return 1;
    }
    // 创建一个与屏幕DC兼容的内存DC
    HDC hMemoryDC = CreateCompatibleDC(hScreenDC);
    if (!hMemoryDC)
    {
        std::cerr << "Failed to create memory DC" << std::endl;
        ReleaseDC(NULL, hScreenDC);
        return 1;
    }
    // 创建一个与屏幕兼容的位图
    HBITMAP hBitmap = CreateCompatibleBitmap(hScreenDC, width, height);
    if (!hBitmap)
    {
        std::cerr << "Failed to create bitmap" << std::endl;
        DeleteDC(hMemoryDC);
        ReleaseDC(NULL, hScreenDC);
        return 1;
    }
    // 将位图选入内存DC
    HGDIOBJ old_obj = SelectObject(hMemoryDC, hBitmap);
    // 捕获屏幕到内存DC
    if (!BitBlt(hMemoryDC, 0, 0, width, height, hScreenDC, 0, 0, SRCCOPY))
    {
        std::cerr << "Failed to capture screen" << std::endl;
        SelectObject(hMemoryDC, old_obj);
        DeleteObject(hBitmap);
        DeleteDC(hMemoryDC);
        ReleaseDC(NULL, hScreenDC);
        return 1;
    }
    // 保存位图
    if (!SaveBitmapToFile(hBitmap, filePath))
    {
        std::cerr << "Failed to save bitmap" << std::endl;
    }
    // 清理资源
    SelectObject(hMemoryDC, old_obj);
    DeleteObject(hBitmap);
    DeleteDC(hMemoryDC);
    ReleaseDC(NULL, hScreenDC);
    return 0;
}
int main(void)
{
    CaptureScreen(L"E:\\output.bmp");
    return 0;
}
    本文为博主总结文章,欢迎转载,请注明出处。

                
            
        
浙公网安备 33010602011771号