2012-03-01 11 views
8

Powiel możliwe:
how to make screen screenshot with win32 in c++?Jak przechwycić część ekranu i zapisać do BMP?

Obecnie próbuję stworzyć aplikację, która zapisana część ekranu do BMP. Znalazłem BitBlt, ale naprawdę nie wiem, co z tym zrobić. Próbowałem szukać odpowiedzi, ale nadal nie znalazłem klarującego jednego przy użyciu C++.

Więc zasadniczo chcę tę funkcję:

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

Co powinno być, że HDC i jak mogę uzyskać BMP?

+1

Spójrz o [SO przedmiotowym] (http://stackoverflow.com/questions/3291167/how-to-make-screen-screenshot -with-win32-in-c). –

+0

Sprawdź to [pytanie] (http://stackoverflow.com/questions/5292700/efficiently-acquiring-o- screens-of-the-windows-desktop), powinno wskazać ci w dobrym kierunku –

+0

@Jesse: Thanks , ten post pomógł mi całkiem sporo :) – Anton

Odpowiedz

17

Zajęło to trochę czasu, ale teraz w końcu skończyło się na skrypcie funkcjonowania.

Wymagania: (?)

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

Również może trzeba dodać ole32, Oleaut32 i UUID do łącznika.

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; 
} 
+0

Dla osób pobierających E_UNEXPECTED po OleCreatePictureIndirect, zapomniałem ustawić PICTDESC.picType na PICTYPE_BMP. –

+0

Notatka dla przyszłych czytelników ... W tym pierwszym bloku kodu 'screenCapturePart' bit, który czyta' BitBlt (hdcMemory, 0, 0, w, h, hdcSource, x, x, SRCCOPY); 'powinien w rzeczywistości być' BitBlt (hdcMemory, 0, 0, w, h, hdcSource, x, y, SRCCOPY); '. –

+0

@ChrisBarlow Naprawiono, dziękuję za uwagę i mówienie! – Anton

3

Możesz użyć GetDC(NULL), aby uzyskać kontekst urządzenia dla całego ekranu, a następnie użyć go z BitBlt jako kontekstu urządzenia źródłowego.

Co do reszty, co robić:

Bitmap Creation (Windows)

Bitmap Storage (Windows)

+0

Tak, wiem, ale nie rozumiem, jak zdefiniować miejsce docelowe hdc. Jak przejść z hdc na bmp? Przepraszam, że nie wyjaśniam tego. – Anton

Powiązane problemy