Why can't I directly send an HBIMAP from a CIm

2019-08-12 18:42发布

I'm working on a small widget, screen capture stuff on Windows.

The core of this program is like the following (I found it on the Internet). First derive from CImage, then add a member function to do this:

BOOL CScreenImage::CaptureRect(const CRect& rect)
{
    // detach and destroy the old bitmap if any attached
    CImage::Destroy();

    // create a screen and a compatible memory device context
    HDC hDCScreen = ::CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
    HDC hDCMem = ::CreateCompatibleDC(hDCScreen);
    //
    // create a bitmap compatible with the screen and select it into the memory DC
    // so you can do whatever you want on the bitmap through the mem DC.
    //
    HBITMAP hBitmap =
    ::CreateCompatibleBitmap(hDCScreen, rect.Width(), rect.Height());
    HBITMAP hBmpOld = (HBITMAP)::SelectObject(hDCMem, hBitmap);
    //
    // bit-blit from screen to memory device context
    // note: CAPTUREBLT flag is required to capture layered windows
    //
    DWORD dwRop = SRCCOPY | CAPTUREBLT;
    BOOL bRet = ::BitBlt(hDCMem, 0, 0, rect.Width(), rect.Height(),
    hDCScreen,
    rect.left, rect.top, dwRop);
    // attach bitmap handle to this object
    Attach(hBitmap);

    // restore the memory DC and perform cleanup
    ::SelectObject(hDCMem, hBmpOld);
    ::DeleteDC(hDCMem);
    ::DeleteDC(hDCScreen);

    return bRet;
}

It worked fine. And if I want to send the bitmap to clipboard, I just need to do the following:

if (::OpenClipboard(hWnd)) {
    HBITMAP hImage = Detach();
    ::EmptyClipboard();
    ::SetClipboardData(CF_BITMAP, hImage);
    ::CloseClipboard();
}

I tested it and I can use it to copy a bitmap from the program to Paint, Word, PowerPoint through the clipboard.

However, what I don't understand is that this dosen't work:

if (::OpenClipboard(this->GetSafeHwnd())) {
    CImage img;
    img.Load(_T("D:\\scc.bmp"));

    ::EmptyClipboard();
    ::SetClipboardData(CF_BITMAP, img.Detach());
    ::CloseClipboard();
}

It seems that some data was indeed sent to the clipboard, but the receiver side (like Paint) would complain "the data on the clipboard cannot be inserted".

Can anyone help? Many thanks.

标签: winapi mfc
1条回答
Juvenile、少年°
2楼-- · 2019-08-12 19:34
CImage* pImage = GetImage();
CDC memDC;
memDC.CreateCompatibleDC(NULL);

CBitmap bitmap;
bitmap.CreateCompatibleBitmap(GetDC(), pImage->GetWidth(), pImage->GetHeight());
memDC.SelectObject(&bitmap);
pImage->BitBlt(memDC.GetSafeHdc(), 0, 0, pImage->GetWidth(), pImage->GetHeight(), 0, 0, SRCCOPY);

EmptyClipboard();
//put the data on the clipboard
SetClipboardData(CF_BITMAP, bitmap.GetSafeHandle());
CloseClipboard();
memDC.DeleteDC();
bitmap.Detach();
查看更多
登录 后发表回答