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

时间:2012-03-01 21:28:56

标签: c++ winapi bmp screen-capture

  

可能重复:
  how to make screen screenshot with win32 in c++?

我目前正在尝试创建一个将屏幕的一部分保存到bmp的应用程序。我找到BitBlt但我真的不知道该怎么做。我试过寻找一些答案,但我还没有找到使用C ++的澄清答案。

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

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
);

该hdc应该是什么以及如何获得bmp?

2 个答案:

答案 0 :(得分:19)

花了一段时间,但我现在终于找到了一个功能正常的脚本。

要求:

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

您也可以(?)将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;
}

答案 1 :(得分:3)

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

至于剩下要做的事情:

Bitmap Creation (Windows)

Bitmap Storage (Windows)