+void ClipboardWin::WriteBitmapFromHandle(HBITMAP source_hbitmap,
+ const gfx::Size& size) {
+ // We would like to just call ::SetClipboardData on the source_hbitmap,
+ // but that bitmap might not be of a sort we can write to the clipboard.
+ // For this reason, we create a new bitmap, copy the bits over, and then
+ // write that to the clipboard.
+
+ HDC dc = ::GetDC(NULL);
+ HDC compatible_dc = ::CreateCompatibleDC(NULL);
+ HDC source_dc = ::CreateCompatibleDC(NULL);
+
+ // This is the HBITMAP we will eventually write to the clipboard
+ HBITMAP hbitmap = ::CreateCompatibleBitmap(dc, size.width(), size.height());
+ if (!hbitmap) {
+ // Failed to create the bitmap
+ ::DeleteDC(compatible_dc);
+ ::DeleteDC(source_dc);
+ ::ReleaseDC(NULL, dc);
+ return;
+ }
+
+ HBITMAP old_hbitmap = (HBITMAP)SelectObject(compatible_dc, hbitmap);
+ HBITMAP old_source = (HBITMAP)SelectObject(source_dc, source_hbitmap);
+
+ // Now we need to blend it into an HBITMAP we can place on the clipboard
+ BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA};
+ ::GdiAlphaBlend(compatible_dc,
+ 0,
+ 0,
+ size.width(),
+ size.height(),
+ source_dc,
+ 0,
+ 0,
+ size.width(),
+ size.height(),
+ bf);
+
+ // Clean up all the handles we just opened
+ ::SelectObject(compatible_dc, old_hbitmap);
+ ::SelectObject(source_dc, old_source);
+ ::DeleteObject(old_hbitmap);
+ ::DeleteObject(old_source);
+ ::DeleteDC(compatible_dc);
+ ::DeleteDC(source_dc);
+ ::ReleaseDC(NULL, dc);
+
+ WriteToClipboard(CF_BITMAP, hbitmap);