如何截取第二个屏幕监视器的屏幕截图?

Posted

技术标签:

【中文标题】如何截取第二个屏幕监视器的屏幕截图?【英文标题】:How to take a screenshot of a second screen monitor? 【发布时间】:2015-03-14 05:59:41 【问题描述】:

我需要获取第二个屏幕监视器的屏幕截图。 我找到了一种制作屏幕截图的简单方法,但仅适用于主显示器的屏幕截图。代码如下:

#include <windows.h>
void ScreenShot(char*BmpName)
    HWND DesktopHwnd = GetDesktopWindow();
    RECT DesktopParams;
    HDC DevC = GetDC(DesktopHwnd);
    GetWindowRect(DesktopHwnd, &DesktopParams);
    DWORD Width = DesktopParams.right - DesktopParams.left;
    DWORD Height = DesktopParams.bottom - DesktopParams.top;

    DWORD FileSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (sizeof(RGBTRIPLE) + 1 * (Width*Height * 4));
    char *BmpFileData = (char*)GlobalAlloc(0x0040, FileSize);

    PBITMAPFILEHEADER BFileHeader = (PBITMAPFILEHEADER)BmpFileData;
    PBITMAPINFOHEADER  BInfoHeader = (PBITMAPINFOHEADER)&BmpFileData[sizeof(BITMAPFILEHEADER)];

    BFileHeader->bfType = 0x4D42; // BM
    BFileHeader->bfSize = sizeof(BITMAPFILEHEADER);
    BFileHeader->bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

    BInfoHeader->biSize = sizeof(BITMAPINFOHEADER);
    BInfoHeader->biPlanes = 1;
    BInfoHeader->biBitCount = 24;
    BInfoHeader->biCompression = BI_RGB;
    BInfoHeader->biHeight = Height;
    BInfoHeader->biWidth = Width;

    RGBTRIPLE *Image = (RGBTRIPLE*)&BmpFileData[sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)];
    RGBTRIPLE color;

    HDC CaptureDC = CreateCompatibleDC(DevC);
    HBITMAP CaptureBitmap = CreateCompatibleBitmap(DevC, Width, Height);
    SelectObject(CaptureDC, CaptureBitmap);
    BitBlt(CaptureDC, 0, 0, Width, Height, DevC, 0, 0, SRCCOPY | CAPTUREBLT);
    GetDIBits(CaptureDC, CaptureBitmap, 0, Height, Image, (LPBITMAPINFO)BInfoHeader, DIB_RGB_COLORS);

    DWORD Junk;
    HANDLE FH = CreateFileA(BmpName, GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, 0, 0);
    WriteFile(FH, BmpFileData, FileSize, &Junk, 0);
    CloseHandle(FH);
    GlobalFree(BmpFileData);


int main()

    ScreenShot("Hello.bmp");

但这仅对默认监视器进行屏幕截图。

如果在演示模式下使用 2 台显示器,我需要拍摄第二台显示器的屏幕截图。

我正在尝试在

上编写相同的代码
EnumDisplayMonitors

像这样:

#include <windows.h>
BOOL CALLBACK MonitorEnumProcCallback(_In_  HMONITOR hMonitor, _In_  HDC DevC, _In_  LPRECT lprcMonitor, _In_  LPARAM dwData) 
    screenCounter++;

    char*BmpName;

    if (screenCounter == 1)
        BmpName = "1 screen.bmp";
    
    else 
        BmpName = "2 screen.bmp";
    


    MONITORINFO  info;
    info.cbSize = sizeof(MONITORINFO);

    BOOL monitorInfo = GetMonitorInfo(hMonitor, &info);

    if (monitorInfo) 

        DWORD Width = info.rcMonitor.right - info.rcMonitor.left;
        DWORD Height = info.rcMonitor.bottom - info.rcMonitor.top;

        DWORD FileSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (sizeof(RGBTRIPLE) + 1 * (Width*Height * 4));
        char *BmpFileData = (char*)GlobalAlloc(0x0040, FileSize);

        PBITMAPFILEHEADER BFileHeader = (PBITMAPFILEHEADER)BmpFileData;
        PBITMAPINFOHEADER  BInfoHeader = (PBITMAPINFOHEADER)&BmpFileData[sizeof(BITMAPFILEHEADER)];

        BFileHeader->bfType = 0x4D42; // BM
        BFileHeader->bfSize = sizeof(BITMAPFILEHEADER);
        BFileHeader->bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

        BInfoHeader->biSize = sizeof(BITMAPINFOHEADER);
        BInfoHeader->biPlanes = 1;
        BInfoHeader->biBitCount = 24;
        BInfoHeader->biCompression = BI_RGB;
        BInfoHeader->biHeight = Height;
        BInfoHeader->biWidth = Width;

        RGBTRIPLE *Image = (RGBTRIPLE*)&BmpFileData[sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)];
        RGBTRIPLE color;

        HDC CaptureDC = CreateCompatibleDC(DevC);
        HBITMAP CaptureBitmap = CreateCompatibleBitmap(DevC, Width, Height);
        SelectObject(CaptureDC, CaptureBitmap);
        BitBlt(CaptureDC, 0, 0, Width, Height, DevC, 0, 0, SRCCOPY | CAPTUREBLT);
        GetDIBits(CaptureDC, CaptureBitmap, 0, Height, Image, (LPBITMAPINFO)BInfoHeader, DIB_RGB_COLORS);

        DWORD Junk;
        HANDLE FH = CreateFileA(BmpName, GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, 0, 0);
        WriteFile(FH, BmpFileData, FileSize, &Junk, 0);
        CloseHandle(FH);
        GlobalFree(BmpFileData);
    

    return TRUE;
 
int main()  
    EnumDisplayMonitors(NULL, NULL, MonitorEnumProcCallback, 0);
    return 0;

但这会返回给我两个黑色图像。

【问题讨论】:

一个相当明显的错误是您仍然将 0, 0 传递给 BitBlt() 而不是显示器的左上角。 【参考方案1】:

感谢@Hans Passant 的帮助。

我改变左上角的值

但我犯了另一个错误,我在 EnumDisplayMonitors 中为第一个参数发送了 NULL。

这里是变化:

BOOL CALLBACK MonitorEnumProcCallback(_In_  HMONITOR hMonitor, _In_  HDC DevC, _In_  LPRECT lprcMonitor, _In_  LPARAM dwData) 
    screenCounter++;

    char*BmpName;

    if (screenCounter == 1)
        BmpName = "1 screen.bmp";
    
    else 
        BmpName = "2 screen.bmp";
    

    MONITORINFO  info;
    info.cbSize = sizeof(MONITORINFO);

    BOOL monitorInfo = GetMonitorInfo(hMonitor, &info);

    if (monitorInfo) 

        DWORD Width = info.rcMonitor.right - info.rcMonitor.left;
        DWORD Height = info.rcMonitor.bottom - info.rcMonitor.top;

        DWORD FileSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (sizeof(RGBTRIPLE) + 1 * (Width*Height * 4));
        char *BmpFileData = (char*)GlobalAlloc(0x0040, FileSize);

        PBITMAPFILEHEADER BFileHeader = (PBITMAPFILEHEADER)BmpFileData;
        PBITMAPINFOHEADER  BInfoHeader = (PBITMAPINFOHEADER)&BmpFileData[sizeof(BITMAPFILEHEADER)];

        BFileHeader->bfType = 0x4D42; // BM
        BFileHeader->bfSize = sizeof(BITMAPFILEHEADER);
        BFileHeader->bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

        BInfoHeader->biSize = sizeof(BITMAPINFOHEADER);
        BInfoHeader->biPlanes = 1;
        BInfoHeader->biBitCount = 24;
        BInfoHeader->biCompression = BI_RGB;
        BInfoHeader->biHeight = Height;
        BInfoHeader->biWidth = Width;

        RGBTRIPLE *Image = (RGBTRIPLE*)&BmpFileData[sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)];
        RGBTRIPLE color;

        HDC CaptureDC = CreateCompatibleDC(DevC);
        HBITMAP CaptureBitmap = CreateCompatibleBitmap(DevC, Width, Height);
        SelectObject(CaptureDC, CaptureBitmap);
        BitBlt(CaptureDC, 0, 0, Width, Height, DevC, info.rcMonitor.left, info.rcMonitor.top, SRCCOPY | CAPTUREBLT);
        GetDIBits(CaptureDC, CaptureBitmap, 0, Height, Image, (LPBITMAPINFO)BInfoHeader, DIB_RGB_COLORS);

        DWORD Junk;
        HANDLE FH = CreateFileA(BmpName, GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, 0, 0);
        WriteFile(FH, BmpFileData, FileSize, &Junk, 0);
        CloseHandle(FH);
        GlobalFree(BmpFileData);
    

    return TRUE;


int main() 

    HDC DevC = GetDC(NULL);
    BOOL b = EnumDisplayMonitors(DevC, NULL, MonitorEnumProcCallback, 0);

    return 0;

【讨论】:

以上是关于如何截取第二个屏幕监视器的屏幕截图?的主要内容,如果未能解决你的问题,请参考以下文章

截取当前未打开的 ViewController 的屏幕截图

如何在颤动中截取屏幕之外的小部件屏幕截图?

如何截取完整滚动文件的屏幕截图

如何使用iOS上的代码截取屏幕截图?

如何以编程方式截取可扩展的uitableview的屏幕截图

如何使用 php 截取已加载网页的屏幕截图? [复制]