2012-03-01 18 views
8

Eventuali duplicati:
how to make screen screenshot with win32 in c++?Come acquisire parte dello schermo e salvarlo su un BMP?

Attualmente sto cercando di creare un'applicazione che ha salvato una parte dello schermo per un bmp. Ho trovato BitBlt ma non so davvero cosa farmene. Ho provato a cercare alcune risposte ma non ho ancora trovato una chiarificazione usando C++.

Quindi, in sostanza voglio questa funzione:

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

Quale dovrebbe essere che hdc e come si ottenere il bmp?

+1

Look at this [domanda SO] (http://stackoverflow.com/questions/3291167/how-to-make-screen-screenshot -con-win32-in-c). –

+0

Dai un'occhiata a questa [domanda] (http://stackoverflow.com/questions/5292700/efficiently-acquiring-a-screenshot-of-the-windows-desktop), dovrebbe indirizzarti nella giusta direzione –

+0

@Jesse: Grazie , quel post mi ha aiutato un po ':) – Anton

risposta

17

è voluto un po, ma ho finalmente finito con uno script funzionamento.

Requisiti: (?)

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

Inoltre potrebbe essere necessario aggiungere ole32, OLEAUT32 e uuid al vostro linker.

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

Per quelli che ricevono E_UNEXPECTED dopo OleCreatePictureIndirect, ho dimenticato di impostare PICTDESC.picType su PICTYPE_BMP. –

+0

Solo una nota per i futuri lettori ... In quel primo blocco di codice 'screenCapturePart' il bit che legge' BitBlt (hdcMemory, 0, 0, w, h, hdcSource, x, x, SRCCOPY); 'in realtà dovrebbe essere' BitBlt (hdcMemory, 0, 0, w, h, hdcSource, x, y, SRCCOPY); '. –

+0

@ChrisBarlow Risolto, grazie per aver notato e detto! – Anton

3

È possibile utilizzare GetDC(NULL) per ottenere il contesto del dispositivo per l'intero schermo, quindi utilizzarlo con BitBlt come contesto del dispositivo di origine.

quanto riguarda il resto di cosa fare:

Bitmap Creation (Windows)

Bitmap Storage (Windows)

+0

Sì, lo so, ma quello che non capisco è come definire l'hdc di destinazione. Come posso passare da un hdc a un bmp? Mi dispiace per non aver chiarito questo. – Anton