본문 바로가기

c c++ mfc

GDI+ 이용한 화면캡쳐

반응형

안녕하세요. 오늘은 Windows에서 제공하는 그래픽 라이브러리인 GDI+(Graphics Device Interface+)를 이용해 화면을 캡쳐하는 방법에 대해 알아보겠습니다.

 

예제 코드는 C++로 작성되었습니다.

먼저, 아래와 같이 필요한 헤더 파일을 포함시킵니다.

#include <windows.h>
#include <gdiplus.h>
#pragma comment(lib, "gdiplus.lib")

 

그리고 다음은 전체 화면을 캡쳐하여 BMP 파일로 저장하는 함수입니다.

void CaptureScreen() {
    using namespace Gdiplus;
    ULONG_PTR gdiplusToken;
    GdiplusStartupInput gdiplusStartupInput;
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

    {
        HDC scrdc = ::GetDC(NULL);
        HDC memdc = CreateCompatibleDC(scrdc);
        int Height = GetSystemMetrics(SM_CYSCREEN), Width = GetSystemMetrics(SM_CXSCREEN);
        HBITMAP hBitmap = CreateCompatibleBitmap(scrdc, Width, Height);
        HBITMAP oldbmp = (HBITMAP)SelectObject(memdc, hBitmap);

        BitBlt(memdc, 0, 0, Width, Height, scrdc, 0 ,0 ,SRCCOPY);

        Bitmap bitmap(hBitmap,NULL); 
        CLSID clsid;  
        
         // 여기서는 BMP 형식으로 저장하도록 하였습니다.
         // 다른 형식으로 저장하려면 해당 형식의 CLSID를 얻어야 합니다.
         GetEncoderClsid(L"image/bmp", &clsid); 

         bitmap.Save(L"screen.bmp", &clsid);

         SelectObject(memdc ,oldbmp);
         
         DeleteObject(hBitmap);
         DeleteDC(memdc); 
         ::ReleaseDC(NULL ,scrdc); 
     }
     GdiplusShutdown(gdiplusToken);
}

위 함수는 GDI+를 초기화한 후 스크린의 DC(Device Context)를 가져와서 그것과 호환되는 메모리 DC를 생성합니다. 그런 다음 BitBlt 함수로 스크린 DC의 내용을 메모리 DC에 복사합니다.

복사된 내용은 GDI+ Bitmap 객체로 변환하고 Save 메소드로 BMP 파일 형태로 저장합니다. 마지막으로 사용했던 자원들을 해제해줍니다.

마지막으로 GetEncoderClsid 함수는 다음과 같습니다.

int GetEncoderClsid(const WCHAR* format, CLSID* pClsid) {
    using namespace Gdiplus;
    UINT  num = 0;          // number of image encoders
    UINT  size = 0;         // size of the image encoder array in bytes

    ImageCodecInfo* pImageCodecInfo = NULL;

    GetImageEncodersSize(&num, &size);
    if(size == 0)
        return -1; 

    pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
    if(pImageCodecInfo == NULL)
        return -1;

     GetImageEncoders(num, size, pImageCodecInfo);

     for(UINT j = 0; j < num; ++j) {
         if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 ) {
             *pClsid = pImageCodecInfo[j].Clsid;
             free(pImageCodecInfo);
             return j;
         }    
     }

     free(pImageCodecInfo);
     return -1;
}

이 함수는 특정 이미지 형식의 인코더를 찾아서 그것의 CLSID를 반환합니다. 이 CLSID가 Bitmap::Save 메소드에 필요한 인자입니다.

이상으로 GDI+를 이용한 화면 캡쳐 방법에 대해 알아보았습니다. 이 코드를 잘 활용하시면 여러분의 프로그램에 스크린 캡쳐 기능을 쉽게 추가할 수 있을 것입니다. 다음 글에서도 유용한 내용으로 찾아오겠습니다.

감사합니다.

반응형