00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "CMSWindowsClipboardBitmapConverter.h"
00020 #include "CLog.h"
00021
00022
00023
00024
00025
00026 CMSWindowsClipboardBitmapConverter::CMSWindowsClipboardBitmapConverter()
00027 {
00028
00029 }
00030
00031 CMSWindowsClipboardBitmapConverter::~CMSWindowsClipboardBitmapConverter()
00032 {
00033
00034 }
00035
00036 IClipboard::EFormat
00037 CMSWindowsClipboardBitmapConverter::getFormat() const
00038 {
00039 return IClipboard::kBitmap;
00040 }
00041
00042 UINT
00043 CMSWindowsClipboardBitmapConverter::getWin32Format() const
00044 {
00045 return CF_DIB;
00046 }
00047
00048 HANDLE
00049 CMSWindowsClipboardBitmapConverter::fromIClipboard(const CString& data) const
00050 {
00051
00052 HGLOBAL gData = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, data.size());
00053 if (gData != NULL) {
00054
00055 char* dst = (char*)GlobalLock(gData);
00056 if (dst != NULL) {
00057 memcpy(dst, data.data(), data.size());
00058 GlobalUnlock(gData);
00059 }
00060 else {
00061 GlobalFree(gData);
00062 gData = NULL;
00063 }
00064 }
00065
00066 return gData;
00067 }
00068
00069 CString
00070 CMSWindowsClipboardBitmapConverter::toIClipboard(HANDLE data) const
00071 {
00072
00073 const char* src = (const char*)GlobalLock(data);
00074 if (src == NULL) {
00075 return CString();
00076 }
00077 UInt32 srcSize = (UInt32)GlobalSize(data);
00078
00079
00080 const BITMAPINFO* bitmap = reinterpret_cast<const BITMAPINFO*>(src);
00081 LOG((CLOG_INFO "bitmap: %dx%d %d", bitmap->bmiHeader.biWidth, bitmap->bmiHeader.biHeight, (int)bitmap->bmiHeader.biBitCount));
00082 if (bitmap->bmiHeader.biPlanes == 1 &&
00083 (bitmap->bmiHeader.biBitCount == 24 ||
00084 bitmap->bmiHeader.biBitCount == 32) &&
00085 bitmap->bmiHeader.biCompression == BI_RGB) {
00086
00087 CString image(src, srcSize);
00088 GlobalUnlock(data);
00089 return image;
00090 }
00091
00092
00093 LOG((CLOG_INFO "convert image from: depth=%d comp=%d", bitmap->bmiHeader.biBitCount, bitmap->bmiHeader.biCompression));
00094 void* raw;
00095 BITMAPINFOHEADER info;
00096 LONG w = bitmap->bmiHeader.biWidth;
00097 LONG h = bitmap->bmiHeader.biHeight;
00098 info.biSize = sizeof(BITMAPINFOHEADER);
00099 info.biWidth = w;
00100 info.biHeight = h;
00101 info.biPlanes = 1;
00102 info.biBitCount = 32;
00103 info.biCompression = BI_RGB;
00104 info.biSizeImage = 0;
00105 info.biXPelsPerMeter = 1000;
00106 info.biYPelsPerMeter = 1000;
00107 info.biClrUsed = 0;
00108 info.biClrImportant = 0;
00109 HDC dc = GetDC(NULL);
00110 HBITMAP dst = CreateDIBSection(dc, (BITMAPINFO*)&info,
00111 DIB_RGB_COLORS, &raw, NULL, 0);
00112
00113
00114 const char* srcBits = (const char*)bitmap + bitmap->bmiHeader.biSize;
00115 if (bitmap->bmiHeader.biBitCount >= 16) {
00116 if (bitmap->bmiHeader.biCompression == BI_BITFIELDS &&
00117 (bitmap->bmiHeader.biBitCount == 16 ||
00118 bitmap->bmiHeader.biBitCount == 32)) {
00119 srcBits += 3 * sizeof(DWORD);
00120 }
00121 }
00122 else if (bitmap->bmiHeader.biClrUsed != 0) {
00123 srcBits += bitmap->bmiHeader.biClrUsed * sizeof(RGBQUAD);
00124 }
00125 else {
00126
00127 srcBits += (1i64 << bitmap->bmiHeader.biBitCount) * sizeof(RGBQUAD);
00128 }
00129
00130
00131 HDC dstDC = CreateCompatibleDC(dc);
00132 HGDIOBJ oldBitmap = SelectObject(dstDC, dst);
00133 SetDIBitsToDevice(dstDC, 0, 0, w, h, 0, 0, 0, h,
00134 srcBits, bitmap, DIB_RGB_COLORS);
00135 SelectObject(dstDC, oldBitmap);
00136 DeleteDC(dstDC);
00137 GdiFlush();
00138
00139
00140 CString image((const char*)&info, info.biSize);
00141 image.append((const char*)raw, 4 * w * h);
00142
00143
00144 DeleteObject(dst);
00145 ReleaseDC(NULL, dc);
00146
00147
00148 GlobalUnlock(data);
00149
00150 return image;
00151 }