더북(TheBook)

4.2.5 클립보드 지원(복사 및 붙여넣기)

클립보드를 이용하면 다른 프로그램과 자료를 교환하기가 용이해진다. IppDib 클래스에서는 비트맵을 클립보드로 복사하는 기능과 클립보드에 있는 비트맵을 가져와서 DIB 객체를 만드는 기능을 제공한다. 클립보드 관련 멤버 함수 선언은 아래와 같다.

• BOOL CopyToClipboard();
• BOOL PasteFromClipboard();

CopyToClipboard 함수는 IppDib 객체가 가지고 있는 DIB 영상을 Windows 클립보드로 복사한다. 반대로 PasteFromClipboard 함수는 클립보드로부터 DIB 내용을 불러와서 IppDib 객체로 변환하는 함수이다. 이 두 함수들의 실제 구현은 소스 4-6에 나타내었으며, 소스 코드에 대한 자세한 설명을 주석으로 대체한다.

소스 4-6 IppDib 클래스 - 클립보드 지원(IppDib.cpp)
BOOL IppDib::CopyToClipboard()
{
    if (!::OpenClipboard(NULL))
        return FALSE;

    // DIB 전체를 전역 메모리 블럭에 복사
    DWORD dwDibSize = GetDibSize();
    HANDLE hDib = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, dwDibSize);
    if (hDib == NULL)
    {
        ::CloseClipboard();
        return FALSE;
    }

    LPVOID lpDib = ::GlobalLock((HGLOBAL)hDib);
    memcpy(lpDib, GetBitmapInfoAddr(), dwDibSize);
    ::GlobalUnlock(hDib);

    // 클립보드에 데이터 입력
    ::EmptyClipboard();
    ::SetClipboardData(CF_DIB, hDib);
    ::CloseClipboard();

    return TRUE;
}

BOOL IppDib::PasteFromClipboard()
{
    // CF_DIB 타입이 아니면 종료한다.
    if (!::IsClipboardFormatAvailable(CF_DIB))
        return FALSE;

    // 클립보드를 연다.
    if (!::OpenClipboard(NULL))
        return FALSE;

    // 클립보드 내용을 받아 온다.
    HANDLE hDib = ::GetClipboardData(CF_DIB);
    if (hDib == NULL)
    {
        ::CloseClipboard();
        return FALSE;
    }

    // 메모리 블럭의 크기는 DIB 전체 크기와 동일
    DWORD dwSize = (DWORD)::GlobalSize((HGLOBAL)hDib);
    LPVOID lpDib = ::GlobalLock((HGLOBAL)hDib);

    LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)lpDib;
    m_nWidth    = lpbi->biWidth;
    m_nHeight   = lpbi->biHeight;
    m_nBitCount = lpbi->biBitCount;

    DWORD dwWidthStep = (DWORD)((m_nWidth * m_nBitCount / 8 + 3) & ~3);
    DWORD dwSizeImage = m_nHeight * dwWidthStep;

    if (m_nBitCount == 24)
        m_nDibSize = sizeof(BITMAPINFOHEADER) + dwSizeImage;
    else
        m_nDibSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * (1 << m_nBitCount) + dwSizeImage;

    // 현재 설정된 IppDib 객체가 있다면 삭제한다.
    if (m_pDib)
        Destroy();

    m_pDib = new BYTE[m_nDibSize];
    if (m_pDib == NULL)
    {
        ::GlobalUnlock(hDib);
        ::CloseClipboard();
        return FALSE;
    }

    memcpy(m_pDib, lpDib, m_nDibSize);
    ::GlobalUnlock(hDib);
    ::CloseClipboard();

    return TRUE;
}