2012-03-01 27 views
8

thể trùng lặp:
how to make screen screenshot with win32 in c++?Cách chụp một phần màn hình và lưu nó vào BMP?

Tôi hiện đang cố gắng để tạo ra một ứng dụng lưu một phần của màn hình để một bmp. Tôi đã tìm thấy BitBlt nhưng tôi thực sự không biết phải làm gì với nó. Tôi đã thử tìm kiếm một số câu trả lời nhưng tôi vẫn chưa tìm được câu trả lời bằng C++.

Vì vậy, về cơ bản tôi muốn chức năng này:

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

nên hdc mà được gì và làm thế nào để có được bmp?

+1

Nhìn này [SO câu hỏi] (http://stackoverflow.com/questions/3291167/how-to-make-screen-screenshot -với-win32-in-c). –

+0

Xem [câu hỏi] này (http://stackoverflow.com/questions/5292700/efficiently-acquiring-a-screenshot-of-the-windows-desktop), nó sẽ chỉ cho bạn đi đúng hướng –

+0

@Jesse: Cảm ơn , bài viết đó đã giúp tôi khá nhiều :) – Anton

Trả lời

17

Phải mất một thời gian, nhưng tôi đã bây giờ cuối cùng đã kết thúc với một kịch bản hoạt động.

Yêu cầu: (?)

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

Ngoài ra bạn có thể phải thêm Ole32, oleaut32 và UUID để mối liên kết của bạn.

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

Đối với những người nhận được E_UNEXPECTED sau OleCreatePictureIndirect, tôi quên đặt PICTDESC.picType thành PICTYPE_BMP. –

+0

Chỉ cần một lưu ý cho người đọc trong tương lai ... Trong đó khối mã đầu tiên 'screenCapturePart' bit đọc' BitBlt (hdcMemory, 0, 0, w, h, hdcSource, x, x, SRCCOPY); 'thực sự nên là' BitBlt (hdcMemory, 0, 0, w, h, hdcSource, x, y, SRCCOPY); –

+0

@ChrisBarlow Đã sửa lỗi, cảm ơn vì đã chú ý và nói! – Anton

3

Bạn có thể sử dụng GetDC(NULL) để nhận bối cảnh thiết bị cho toàn bộ màn hình, sau đó sử dụng ngữ cảnh đó với BitBlt làm ngữ cảnh thiết bị nguồn.

Đối với phần còn lại của những việc cần làm:

Bitmap Creation (Windows)

Bitmap Storage (Windows)

+0

Vâng tôi biết, nhưng những gì tôi không hiểu là làm thế nào để xác định hdc đích. Làm thế nào để tôi đi từ một hdc đến một bmp? Xin lỗi vì đã không làm rõ điều đó. – Anton

Các vấn đề liên quan