简体   繁体   中英

WinAPI: Correctly copying a HBITMAP to the clipboard

I have some difficulties trying to copy a HBITMAP to the clipboard. My HBITMAP is created from a COLORREF array and I am able to display it correctly. Here is how it is created:

COLORREF* colors = new COLORREF[imageSize[0] * imageSize[1]];

for (int i = 0; i < imageSize[1]; i++) {
    for (int j = 0; j < imageSize[0]; j++) {
        colors[imageSize[0] * i + j] = RGB(/* ... */);
    }
}

// Create bitmap
HBITMAP hBitmap = CreateBitmap(imageSize[0], imageSize[1], 1, 32, (void*)colors);

delete[] colors;

In order to copy my bitmap to the clipboard, I use this small piece of code:

OpenClipboard(hWnd);
EmptyClipboard();

SetClipboardData(CF_BITMAP, hBitmap);

CloseClipboard();

When I execute my app, I am able to copy the bitmap and paste it somewhere, for example in MS Paint. But if I try to copy it a second time, the clipboard content can't be pasted anymore unless the first piece of code above is executed again.

In the MSDN documentation , it is said that

If SetClipboardData succeeds, the system owns the object identified by the hMem parameter.

I don't understand exactly what this means, but I guess it is the source of my problem. I found an example of a function which does what I want here , but it does not seem to use the same kind of variables. Another example, using strings this time, can be found here .

I am not too sure how to translate this last example to my case. Could you point me in the right direction?

A comment that was deleted helped me find the answer. I actually have to copy my HBITMAP to another HBITMAP before calling SetClipboardData . This way, the copied bitmap can be sent to the clipboard, and the original bitmap is kept for later.

To copy the bitmap, I used the code that can be found in Copying a Bitmap to another Bitmap . In my code, it looks like this:

// Create a new bitmap
HBITMAP hBitmap_copy = CreateBitmap(imageSize[0], imageSize[1], 1, 32, NULL);

// Copy the source bitmap to the new one    
HDC srcDC = CreateCompatibleDC(GetDC(NULL));
HDC newDC = CreateCompatibleDC(GetDC(NULL));

HBITMAP srcBitmap = (HBITMAP)SelectObject(srcDC, hBitmap);
HBITMAP newBitmap = (HBITMAP)SelectObject(newDC, hBitmap_copy);

BitBlt(newDC, 0, 0, imageSize[0], imageSize[1], srcDC, 0, 0, SRCCOPY);

SelectObject(srcDC, srcBitmap);
SelectObject(newDC, newBitmap);

DeleteDC(srcDC);
DeleteDC(newDC);

// hBitmap_copy can now be copied to the clipboard
OpenClipboard(hWnd);
EmptyClipboard();   

SetClipboardData(CF_BITMAP, hBitmap_copy);

CloseClipboard();

I can now copy the displayed bitmap as many times as I want!

// You can't pass hBitmap to SetClipboardData directly
OpenClipboard(NULL)
HBITMAP hBitmap = getBit(); // From somewhere

DIBSECTION ds;
::GetObject(hBitmap, sizeof(DIBSECTION), &ds);
//make sure compression is BI_RGB
ds.dsBmih.biCompression = BI_RGB;
HDC hdc = ::GetDC(NULL);
HBITMAP hbitmap_ddb = ::CreateDIBitmap(
    hdc, &ds.dsBmih, CBM_INIT, ds.dsBm.bmBits, (BITMAPINFO*)&ds.dsBmih, DIB_RGB_COLORS);
::ReleaseDC(NULL, hdc);

EmptyClipboard();
SetClipboardData(CF_BITMAP, hbitmap_ddb);
CloseClipboard();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM