2012-03-01 29 views
8

可能性の重複:
how to make screen screenshot with win32 in c++?画面の一部をキャプチャしてBMPに保存する方法は?

私は現在、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を得るのですか?

+1

これを見てhttp://stackoverflow.com/questions/3291167/how-to-make-screen-screenshot([SO質問] -with-win32-in-c)。 –

+0

この[質問](http://stackoverflow.com/questions/5292700/efficiently-acquiring-a-screenshot-of-the-windows-desktop)をチェックすると、正しい方向を指すはずです –

+0

@Jesse:ありがとう、そのポストは私をかなり助けました:) – Anton

答えて

17

それはしばらく時間がかかったが、私は今、最終的には機能しているスクリプトになってしまっています。

要件:(?)

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

OleCreatePictureIndirectの後でE_UNEXPECTEDを取得する人のために、PICTDESC.picTypeをPICTYPE_BMPに設定するのを忘れました。 –

+0

今後の読者のためのメモ...最初のコードブロック 'screenCapturePart'では' BitBlt(hdcMemory、0、0、w、h、hdcSource、x、x、SRCCOPY);を読み込むビットは実際に 'BitBlt (hdcMemory、0、0、w、h、hdcSource、x、y、SRCCOPY); '。 –

+0

@ChrisBarlow固定して、気づいてくれてありがとう! – Anton

3

GetDC(NULL)を使用すると、画面全体のデバイスコンテキストを取得し、ソースデバイスコンテキストとしてBitBltを使用することができます。

は何をすべきかの残りの部分については:

Bitmap Creation (Windows)

Bitmap Storage (Windows)

+0

はいわかりますが、私が理解していないことは、目的地のhdcを定義する方法です。どのようにhdcからbmpに行くのですか?申し訳ありませんが、それを明確にしていません。 – Anton

関連する問題