C++ 如何捕获屏幕的一部分并将其保存到 BMP?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9524393/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 12:55:29  来源:igfitidea点击:

How to capture part of the screen and save it to a BMP?

c++winapibmpscreen-capture

提问by Anton

Possible Duplicate:
how to make screen screenshot with win32 in c++?

可能的重复:
如何在 c++ 中使用 win32 制作屏幕截图?

I am currently trying to create an application that saved a portion of the screen to a bmp. I have found BitBltbut I really don't know what to do with it. I have tried searching for some answers but I still haven't found a clarifying one using C++.

我目前正在尝试创建一个将屏幕的一部分保存到 bmp 的应用程序。我找到了BitBlt,但我真的不知道如何处理它。我试过寻找一些答案,但我仍然没有找到一个使用 C++ 的澄清答案。

So, basically I want this function:

所以,基本上我想要这个功能:

bool capturePartScreen(int x, int y, int w int, h, string dest){
    //Capture part of screen according to coordinates, width and height.
    //Save that captured image as a bmp to dest.
    //Return true if success, false if failure
}

BitBlt:

比特比特:

BOOL BitBlt(
    __in  HDC hdcDest,
    __in  int nXDest,
    __in  int nYDest,
    //The three above are the ones I don't understand!
    __in  int nWidth,
    __in  int nHeight,
    __in  HDC hdcSrc,
    __in  int nXSrc,
    __in  int nYSrc,
    __in  DWORD dwRop
);

What should that hdc be and how do I obtain the bmp?

hdc 应该是什么,我如何获得 bmp?

回答by Anton

It took a while, but I have now finally ended up with a functioning script.

花了一段时间,但我现在终于得到了一个可以运行的脚本。

Requirements:

要求:

#include <iostream>
#include <ole2.h>
#include <olectl.h>

Also you might(?) have to add ole32, oleaut32 and uuid to your linker.

此外,您可能(?)必须将 ole32、oleaut32 和 uuid 添加到您的链接器中。

screenCapturePart:

屏幕捕获部分:

bool screenCapturePart(int x, int y, int w, int h, LPCSTR fname){
    HDC hdcSource = GetDC(NULL);
    HDC hdcMemory = CreateCompatibleDC(hdcSource);

    int capX = GetDeviceCaps(hdcSource, HORZRES);
    int capY = GetDeviceCaps(hdcSource, VERTRES);

    HBITMAP hBitmap = CreateCompatibleBitmap(hdcSource, w, h);
    HBITMAP hBitmapOld = (HBITMAP)SelectObject(hdcMemory, hBitmap);

    BitBlt(hdcMemory, 0, 0, w, h, hdcSource, x, y, SRCCOPY);
    hBitmap = (HBITMAP)SelectObject(hdcMemory, hBitmapOld);

    DeleteDC(hdcSource);
    DeleteDC(hdcMemory);

    HPALETTE hpal = NULL;
    if(saveBitmap(fname, hBitmap, hpal)) return true;
    return false;
}

saveBitmap:

保存位图:

bool saveBitmap(LPCSTR filename, HBITMAP bmp, HPALETTE pal)
{
    bool result = false;
    PICTDESC pd;

    pd.cbSizeofstruct   = sizeof(PICTDESC);
    pd.picType      = PICTYPE_BITMAP;
    pd.bmp.hbitmap  = bmp;
    pd.bmp.hpal     = pal;

    LPPICTURE picture;
    HRESULT res = OleCreatePictureIndirect(&pd, IID_IPicture, false,
                       reinterpret_cast<void**>(&picture));

    if (!SUCCEEDED(res))
    return false;

    LPSTREAM stream;
    res = CreateStreamOnHGlobal(0, true, &stream);

    if (!SUCCEEDED(res))
    {
    picture->Release();
    return false;
    }

    LONG bytes_streamed;
    res = picture->SaveAsFile(stream, true, &bytes_streamed);

    HANDLE file = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ, 0,
                 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);

    if (!SUCCEEDED(res) || !file)
    {
    stream->Release();
    picture->Release();
    return false;
    }

    HGLOBAL mem = 0;
    GetHGlobalFromStream(stream, &mem);
    LPVOID data = GlobalLock(mem);

    DWORD bytes_written;

    result   = !!WriteFile(file, data, bytes_streamed, &bytes_written, 0);
    result  &= (bytes_written == static_cast<DWORD>(bytes_streamed));

    GlobalUnlock(mem);
    CloseHandle(file);

    stream->Release();
    picture->Release();

    return result;
}

回答by MSN

You can use GetDC(NULL)to get the device context for the entire screen, then use that with BitBltas the source device context.

您可以使用GetDC(NULL)获取整个屏幕的设备上下文,然后将其BitBlt用作源设备上下文。

As for the rest of what to do:

至于剩下的要做的事情:

Bitmap Creation (Windows)

位图创建 (Windows)

Bitmap Storage (Windows)

位图存储 (Windows)