简体   繁体   English

在 Windows 中截取屏幕将输出黑屏图像

[英]Taking a screenshot in Windows will output a black screen image

I'm trying to take a full page screenshot in windows.我正在尝试在 Windows 中截取整页屏幕截图。 function works in first call but after second call won't work at all and it's just getting a black screen image with a stable size.函数在第一次调用时工作,但在第二次调用后根本不起作用,它只是得到一个大小稳定的黑屏图像。 when i use debugger the function works well without giving the black screen.当我使用调试器时,该功能运行良好而不会出现黑屏。

Here is the code:这是代码:

void screenshot(std::string imageaPath)
{
    ULONG_PTR gdiplustoken;
    Gdiplus::GdiplusStartupInput gdistartupinput;
    Gdiplus::GdiplusStartupOutput gdistartupoutput;

    gdistartupinput.SuppressBackgroundThread = true;
    GdiplusStartup(&gdiplustoken, &gdistartupinput, &gdistartupoutput); //start GDI+

    HDC hScreenDC = GetDC(GetDesktopWindow());
    HDC hMemoryDC = CreateCompatibleDC(hScreenDC);

    int cx = GetSystemMetrics(SM_CXVIRTUALSCREEN);
    int cy = GetSystemMetrics(SM_CYVIRTUALSCREEN);
    int x = GetSystemMetrics(SM_XVIRTUALSCREEN); 
    int y = GetSystemMetrics(SM_YVIRTUALSCREEN);

    HBITMAP hbitmap = CreateCompatibleBitmap(hScreenDC, cx, cy);
    HBITMAP holdbitmap = static_cast<HBITMAP>(SelectObject(hMemoryDC, hbitmap));

    BitBlt(hMemoryDC, 0, 0, cx, cy, hScreenDC, x, y, SRCCOPY | CAPTUREBLT);
    hbitmap = static_cast<HBITMAP>(SelectObject(hMemoryDC, holdbitmap));    

    UINT num, size;

    Gdiplus::ImageCodecInfo* imagecodecinfo;
    Gdiplus::GetImageEncodersSize(&num, &size); // get count of codec

    imagecodecinfo = (Gdiplus::ImageCodecInfo*)(malloc(size));
    GetImageEncoders(num, size, imagecodecinfo);//get codec

    CLSID clsidEncoder;

    for (int i = 0; i < num; i++)
    {
        if (wcscmp(imagecodecinfo[i].MimeType, L"image/jpeg") == 0)
            clsidEncoder = imagecodecinfo[i].Clsid; // get jpeg codec id
    }

    free(imagecodecinfo);
    Gdiplus::Bitmap* bm = new Gdiplus::Bitmap(hbitmap, NULL);
    std::wstring ws;
    ws.assign(imageaPath.begin(), imageaPath.end());//sring to wstring
    bm->Save(ws.c_str(), &clsidEncoder); //save in jpeg format
    SelectObject(hMemoryDC, holdbitmap);//Release Objects
    DeleteObject(hMemoryDC);
    DeleteObject(hbitmap);
    ReleaseDC(GetDesktopWindow(), hScreenDC);

    Gdiplus::GdiplusShutdown(gdiplustoken);
}

update:更新:

Okay i find a way to take a screenshot without black screen image when i use system("pause");好的,当我使用system("pause");时,我找到了一种在没有黑屏图像的情况下截取屏幕截图的方法system("pause"); to make program stop and when press enter to make program continue, it's working, I used c++ sleep methods but not works, any idea?使程序停止,当按回车键使程序继续时,它正在工作,我使用了 c++ sleep 方法但不起作用,知道吗?

...
HBITMAP holdbitmap = static_cast<HBITMAP>(SelectObject(hMemoryDC, hbitmap));

system("pause");

BitBlt(hMemoryDC, 0, 0, cx, cy, hScreenDC, x, y, SRCCOPY | CAPTUREBLT);
...

sleep methods:睡眠方法:

Sleep(1000);
std::this_thread::sleep_for(std::chrono::seconds(1));

update 2:更新2:

I was sending screenshot request using curl and I was testing in a server(rdp) when I was logged out I was sending request, I think sleep mode in server is enabled and when I logged out the server will be sleep and it's like computer screen to go dark and that's why BitBlt() fails and GetLastError() will return 5 which means access denied我正在使用 curl 发送屏幕截图请求,当我注销时我正在服务器(rdp)中进行测试我正在发送请求,我认为服务器中的睡眠模式已启用,当我注销时,服务器将进入睡眠状态,就像电脑屏幕一样变暗,这就是为什么 BitBlt() 失败并且 GetLastError() 将返回 5,这意味着访问被拒绝

The documentation for GdiplusShutdown says that GdiplusShutdown的文档

You must call GdiplusStartup before you create any GDI+ objects, and you must delete all of your GDI+ objects (or have them go out of scope) before you call GdiplusShutdown .你必须调用GdiplusStartup创建任何GDI +对象之前,你必须删除所有的GDI +对象(或让他们走出去的范围),在打电话前GdiplusShutdown

You are leaking bm = new Gdiplus::Bitmap(...) which is violating this rule.您正在泄漏违反此规则的bm = new Gdiplus::Bitmap(...)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM