2012-03-01 40 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

看這個[SO問題](http://stackoverflow.com/questions/3291167/how-to-make-screen-screenshot -with-Win32的在-C)。 – 2012-03-01 21:48:28

+0

看看這個[問題](http://stackoverflow.com/questions/5292700/efficiently-acquiring-a-screenshot-of-the-windows-desktop),它應該指向你在正確的方向 – 2012-03-01 22:30:04

+0

@Jesse:謝謝,該帖子幫了我很多:) – Anton 2012-03-01 23:25:45

回答

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。 – 2013-04-27 16:08:50

+0

給未來的讀者一個提示......在第一個代碼塊'screenCapturePart'中,讀BitBlt(hdcMemory,0,0,w,h,hdcSource,x,x,SRCCOPY)的位實際上應該是BitBlt (hdcMemory,0,0,w,h,hdcSource,x,y,SRCCOPY);'。 – 2014-02-06 22:29:38

+0

@ChrisBarlow修復,感謝您的注意和告訴! – Anton 2014-02-08 20:45:34

3

您可以使用GetDC(NULL)獲取整個屏幕的設備上下文,然後使用BitBlt作爲源設備上下文。

至於做什麼的休息:

Bitmap Creation (Windows)

Bitmap Storage (Windows)

+0

是的,我知道,但我不明白的是如何定義目標hdc。我如何從一個hdc到一個bmp?對不起,沒有澄清。 – Anton 2012-03-01 21:35:36