2012-03-01 9 views
8

Duplicar posible:
how to make screen screenshot with win32 in c++?Cómo capturar parte de la pantalla y guardarla en un BMP?

Actualmente estoy tratando de crear una aplicación que guarda una parte de la pantalla a un bmp. He encontrado BitBlt pero realmente no sé qué hacer con él. Intenté buscar algunas respuestas, pero todavía no encontré una aclaración usando C++.

Así que, básicamente, quiero esta función:

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

Lo que debería ser HDC y cómo puedo obtener el BMP?

+1

Mira esta [pregunta SO] (http://stackoverflow.com/questions/3291167/how-to-make-screen-screenshot -with-win32-in-c). –

+0

Mira esta [pregunta] (http://stackoverflow.com/questions/5292700/efficiently-acquiring-a-screenshot-of-the-windows-desktop), debe indicarte la dirección correcta –

+0

@Jesse: Gracias , esa publicación me ayudó bastante :) – Anton

Respuesta

17

Me tomó un tiempo, pero ahora por fin han terminado con un guión funcionamiento.

Requisitos: (?)

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

También es posible que tenga que añadir OLE32, OLEAUT32 y uuid a su enlazador.

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

Para aquellos que obtienen E_UNEXPECTED después de OleCreatePictureIndirect, olvidé establecer PICTDESC.picType en PICTYPE_BMP. –

+0

Sólo una nota para lectores futuros ... En ese primer bloque de código 'screenCapturePart' el bit que dice' BitBlt (hdcMemory, 0, 0, w, h, hdcSource, x, x, SRCCOPY); 'debería ser realmente' BitBlt (hdcMemory, 0, 0, w, h, hdcSource, x, y, SRCCOPY); '. –

+0

@ChrisBarlow ¡Reparado, gracias por notarlo y contarlo! – Anton

3

Puede usar GetDC(NULL) para obtener el contexto del dispositivo para toda la pantalla, y luego usarlo con BitBlt como contexto del dispositivo de origen.

En cuanto al resto de lo que debe hacer:

Bitmap Creation (Windows)

Bitmap Storage (Windows)

+0

Sí, lo sé, pero lo que no entiendo es cómo definir el hdc de destino. ¿Cómo paso de un hdc a un bmp? Perdón por no aclarar eso. – Anton

Cuestiones relacionadas