Bitmaps are saved incorrectly into the Windows clipboard
Original Reporter info from Mantis: mishob
-
Reporter name: Mihail Balabanov
Original Reporter info from Mantis: mishob
- Reporter name: Mihail Balabanov
Description:
It appears that LCL currently cannot send a bitmap into the system clipboard so that it can be retrieved from another Windows application.
Using registered clipboard formats that have associated MIME types seems to work fine, but they are not guaranteed to be supported by standard Windows applications. The problem arises when one wants to transfer bitmaps to another application using the standard Windows clipboard format, CF_BITMAP.
Steps to reproduce:
Image is a TImage containing a TBitmap. Try any of the following:
Clipboard.Assign(Image.Picture.Bitmap); // Supposedly the correct way?
Image.Picture.Bitmap.SaveToClipboardFormat(PredefinedClipboardFormat(pcfBitmap));
Image.Picture.Bitmap.SaveToClipboardFormat(CF_BITMAP);
- After any of the above, the only available format in the clipboard is CF_BITMAP (ID = 2). This means Windows is unable to perform its implicit conversions to CF_DIB and CF_DIBV5 (these are performed automatically every time when one of these three formats gets stored into the system clipboard; see the section about synthesized clipboard formats here: http://msdn.microsoft.com/en-us/library/ms649013(VS.85).aspx).
- After selecting Edit | Paste in MS Paint, it says "Error getting the Clipboard Data!".
- Trying to load the image from the clipboard in a LCL application fails.
Additional information:
(for more context, see this thread in the forums: http://www.lazarus.freepascal.org/index.php?name=PNphpBB2&file=viewtopic&t=5979)
It seems that the actual data transferred by the Win32 widgetset (by saving the TBitmap to a stream and then copying its contents to the clipboard) are not what standard Windows API applications expect for a CF_BITMAP. If you copy the bitmap into one created using Windows API, it is processed correctly and is available for correct pasting into other Windows applications. The following code does that:
procedure TForm1.btnCopyResultClick(Sender: TObject);
var
MemDC: HDC;
MemBitmap, OldBitmap: HBITMAP;
W, H: Integer;
begin
W := Image3.Picture.Bitmap.Width;
H := Image3.Picture.Bitmap.Height;
MemDC := Windows.CreateCompatibleDC(Canvas.Handle);
MemBitmap := Windows.CreateCompatibleBitmap(Canvas.Handle, W, H);
OldBitmap := Windows.SelectObject(MemDC, MemBitmap);
Windows.BitBlt(MemDC, 0, 0, W, H, Image.Picture.Bitmap.Canvas.Handle, 0, 0, SRCCOPY);
Windows.OpenClipboard(Handle);
Windows.EmptyClipboard;
Windows.SetClipboardData(CF_BITMAP, MemBitmap);
Windows.CloseClipboard;
Windows.SelectObject(MemDC, OldBitmap);
Windows.DeleteDC(MemDC);
Windows.DeleteObject(MemBitmap);
end;
This is the solution I am currently using for putting bitmaps on the clipboard but it is just a hack. It will be good to have this functionality working in the Windows widgetset.
Mantis conversion info:
- Mantis ID: 12729
- OS: Windows
- OS Build: Windows XP
- Platform: Win32
- Version: 0.9.26
- Fixed in version: 0.9.27 (SVN)
- Fixed in revision: 18309 (#252c07b6)
- Monitored by: » mishob (Mihail Balabanov)
- Target version: 0.9.28