C++ 可靠的屏幕截图方法-在Windows 10中提供透明区域

C++ 可靠的屏幕截图方法-在Windows 10中提供透明区域,c++,winapi,C++,Winapi,我用这种可靠的方法截图。我称之为“可靠”,因为它在XP之后的所有Windows版本中都适用。然而在Win10中,它现在为我提供了透明部分。某些类型的窗口中的某些区域是透明的,我无法解释 这是一个屏幕截图,键盘上有正常的打印屏幕键- 这是使用下面我的代码的同一部分的屏幕截图- 文件类型为“文件资源管理器”的窗口的某些区域似乎变得透明。不过上面的截图是记事本+ 这是我的算法: #include <Windows.h> #include <stdio.h> int WIN

我用这种可靠的方法截图。我称之为“可靠”,因为它在XP之后的所有Windows版本中都适用。然而在Win10中,它现在为我提供了透明部分。某些类型的窗口中的某些区域是透明的,我无法解释

这是一个屏幕截图,键盘上有正常的打印屏幕键-

这是使用下面我的代码的同一部分的屏幕截图-

文件类型为“文件资源管理器”的窗口的某些区域似乎变得透明。不过上面的截图是记事本+

这是我的算法:

#include <Windows.h>
#include <stdio.h>

int WINAPI WinMain(HINSTANCE hinst, HINSTANCE, LPSTR, int)
{
    MessageBox(0, L"Hello World", L"Unipen", MB_ICONINFORMATION);


    int i = 0;
    DISPLAY_DEVICE device;

    device.cb = sizeof(device);


    while (EnumDisplayDevices(NULL, i, &device, 0) && ++i) {
        if ((device.StateFlags & DISPLAY_DEVICE_ACTIVE) != DISPLAY_DEVICE_ACTIVE) {
            MessageBox(0, device.DeviceName, L"CONTINUE", MB_ICONINFORMATION);
            continue;
        }
        MessageBox(0, device.DeviceName, L"BREAK", MB_ICONINFORMATION);
        break;
    }

    size_t screenWidth = 1920;
    size_t screenHeight = 1200;
    size_t colorLen = 4;

    HDC hdcScreen;
    hdcScreen = CreateDC(NULL, device.DeviceName, NULL, NULL);
    if (hdcScreen == (HDC)NULL) {
        MessageBox(0, L"UnableToCreateDC", L"ERROR", MB_ICONINFORMATION);
        return 0;
    }

    HDC hdcMemoryDC;
    hdcMemoryDC = CreateCompatibleDC(hdcScreen);
    if (hdcMemoryDC == (HDC)NULL) {
        DeleteDC(hdcScreen);
        MessageBox(0, L"UnableToCreateCompatibleDC", L"ERROR", MB_ICONINFORMATION);
        return 0;
    }

    BITMAPINFO bmi;
    bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmi.bmiHeader.biWidth = (LONG)screenWidth;
    bmi.bmiHeader.biHeight = (-1)*(LONG)screenHeight;
    bmi.bmiHeader.biPlanes = 1;
    bmi.bmiHeader.biBitCount = 32;
    bmi.bmiHeader.biCompression = BI_RGB;

    BYTE *pixelBuffer;
    HBITMAP hbmp;
    hbmp = CreateDIBSection(hdcScreen, &bmi, DIB_RGB_COLORS, (void **)&pixelBuffer, NULL, 0);
    if (hbmp == (HBITMAP)NULL) {
        DeleteDC(hdcScreen);
        DeleteDC(hdcMemoryDC);
        MessageBox(0, L"UnableToCreateDIBSection", L"ERROR", MB_ICONINFORMATION);
        return 0;
    }

    //HGDIOBJ rez_selected;
    HBITMAP rez_selected_bmp;
    rez_selected_bmp = (HBITMAP)SelectObject(hdcMemoryDC, hbmp);
    if (rez_selected_bmp == (HBITMAP)NULL) {
        DeleteDC(hdcScreen);
        DeleteDC(hdcMemoryDC);
        DeleteObject(hbmp);
        MessageBox(0, L"UnableToCreateDIBSection", L"ERROR", MB_ICONINFORMATION);
        return 0;
    }

    BitBlt(hdcMemoryDC, 0, 0, screenWidth, screenHeight, hdcScreen, 0, 0, SRCCOPY);


    //(void) SelectObject(hdcMemoryDC, rez_selected_bmp);

    if (fopen_s(&stream, "C:\\Users\Vayeate\\Desktop\\blah.txt", "w") == 0) {
        for(size_t px = 0 ; px < (screenHeight * screenWidth * 4) ; ++px) {
            fprintf(stream, "%hhu, ", pixelBuffer[px]);
        }
        fclose(stream);
    }

    DeleteDC(hdcScreen);
    DeleteDC(hdcMemoryDC);
    DeleteObject(hbmp);

    MessageBox(0, L"DONE", L"Unipen", MB_ICONINFORMATION);

    return 0;
}
#包括
#包括
int WINAPI WinMain(HINSTANCE hinst、HINSTANCE、LPSTR、int)
{
MessageBox(0,L“Hello World”,L“Unipen”,MB_图标信息);
int i=0;
显示装置;
device.cb=sizeof(设备);
while(EnumDisplayDevices(NULL、i和device、0)和&++i){
如果((device.StateFlags&DISPLAY\u device\u ACTIVE)!=DISPLAY\u device\u ACTIVE){
MessageBox(0,device.DeviceName,L“CONTINUE”,MB_图标信息);
继续;
}
MessageBox(0,device.DeviceName,L“BREAK”,MB_图标信息);
打破
}
尺寸\u t屏幕宽度=1920;
尺寸\u t屏幕高度=1200;
颜色长度=4;
HDC-hdcScreen;
hdcScreen=CreateDC(NULL,device.DeviceName,NULL,NULL);
if(hdcScreen==(HDC)NULL){
消息框(0,L“无法创建DC”,L“错误”,MB_图标信息);
返回0;
}
HDC-hdcMemoryDC;
hdcMemoryDC=CreateCompatibleDC(hdcScreen);
if(hdcMemoryDC==(HDC)NULL){
DeleteDC(hdcScreen);
消息框(0,L“无法创建兼容的C”,L“错误”,MB\u图标信息);
返回0;
}
BITMAPINFO bmi;
bmi.bmiHeader.biSize=sizeof(BitMapInfo头文件);
bmi.bmiHeader.biWidth=(长)屏幕宽度;
bmi.bmiHeader.biHeight=(-1)*(长)屏幕高度;
bmi.bmiHeader.biPlanes=1;
bmi.bmiHeader.biBitCount=32;
bmi.bmiHeader.biCompression=BI_RGB;
字节*像素缓冲区;
HBITMAP-hbmp;
hbmp=CreateDIBSection(hdcScreen和bmi,DIB_RGB_颜色,(void**)和pixelBuffer,NULL,0);
如果(hbmp==(HBITMAP)为空){
DeleteDC(hdcScreen);
DeleteDC(hdcMemoryDC);
消息框(0,L“无法创建节”,L“错误”,MB_图标信息);
返回0;
}
//Hgdobj rez_入选;
HBITMAP rez_选定的bmp;
rez_selected_bmp=(HBITMAP)SelectObject(hdcMemoryDC,hbmp);
如果(rez_selected_bmp==(HBITMAP)NULL){
DeleteDC(hdcScreen);
DeleteDC(hdcMemoryDC);
删除对象(hbmp);
消息框(0,L“无法创建节”,L“错误”,MB_图标信息);
返回0;
}
BitBlt(hdcMemoryDC,0,0,屏幕宽度,屏幕高度,hdcScreen,0,0,SRCCOPY);
//(无效)选择对象(hdcMemoryDC,rez_selected_bmp);
如果(fopen_s(&stream,“C:\\Users\Vayeate\\Desktop\\blah.txt”,“w”)==0){
用于(尺寸px=0;px<(屏幕高度*屏幕宽度*4);+px){
fprintf(流,'%hhu',像素缓冲区[px]);
}
fclose(流);
}
DeleteDC(hdcScreen);
DeleteDC(hdcMemoryDC);
删除对象(hbmp);
消息框(0,L“完成”,L“Unipen”,MB_图标信息);
返回0;
}

尝试将alpha频道设置为255或使用不使用alpha频道的图像格式。尝试按键盘上的“打印屏幕”。哇,谢谢@RossRidge修复了它!为什么在以前的Windows版本中,每个透明度值始终为255?另请参阅本文,使用
GetDIBits
将屏幕保存到位图文件,并注意
GetClientRect
获取屏幕大小。这是一个圆满的结局!我想24bpp像素格式是最简单的解决方案。尝试将alpha通道设置为255或使用不使用的图像格式。尝试按键盘上的“打印屏幕”。哇,谢谢@RossRidge修复了它!为什么在以前的Windows版本中,每个透明度值始终为255?另请参阅本文,使用
GetDIBits
将屏幕保存到位图文件,并注意
GetClientRect
获取屏幕大小。这是一个圆满的结局!我想24bpp像素格式是最简单的解决方案。