1 | /*
|
---|
2 | * synergy -- mouse and keyboard sharing utility
|
---|
3 | * Copyright (C) 2004 Chris Schoeneman
|
---|
4 | *
|
---|
5 | * This package is free software; you can redistribute it and/or
|
---|
6 | * modify it under the terms of the GNU General Public License
|
---|
7 | * found in the file COPYING that should have accompanied this file.
|
---|
8 | *
|
---|
9 | * This package is distributed in the hope that it will be useful,
|
---|
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
12 | * GNU General Public License for more details.
|
---|
13 | */
|
---|
14 |
|
---|
15 | #include "CMSWindowsClipboardBitmapConverter.h"
|
---|
16 | #include "CLog.h"
|
---|
17 |
|
---|
18 | //
|
---|
19 | // CMSWindowsClipboardBitmapConverter
|
---|
20 | //
|
---|
21 |
|
---|
22 | CMSWindowsClipboardBitmapConverter::CMSWindowsClipboardBitmapConverter()
|
---|
23 | {
|
---|
24 | // do nothing
|
---|
25 | }
|
---|
26 |
|
---|
27 | CMSWindowsClipboardBitmapConverter::~CMSWindowsClipboardBitmapConverter()
|
---|
28 | {
|
---|
29 | // do nothing
|
---|
30 | }
|
---|
31 |
|
---|
32 | IClipboard::EFormat
|
---|
33 | CMSWindowsClipboardBitmapConverter::getFormat() const
|
---|
34 | {
|
---|
35 | return IClipboard::kBitmap;
|
---|
36 | }
|
---|
37 |
|
---|
38 | UINT
|
---|
39 | CMSWindowsClipboardBitmapConverter::getWin32Format() const
|
---|
40 | {
|
---|
41 | return CF_DIB;
|
---|
42 | }
|
---|
43 |
|
---|
44 | HANDLE
|
---|
45 | CMSWindowsClipboardBitmapConverter::fromIClipboard(const CString& data) const
|
---|
46 | {
|
---|
47 | // copy to memory handle
|
---|
48 | HGLOBAL gData = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, data.size());
|
---|
49 | if (gData != NULL) {
|
---|
50 | // get a pointer to the allocated memory
|
---|
51 | char* dst = (char*)GlobalLock(gData);
|
---|
52 | if (dst != NULL) {
|
---|
53 | memcpy(dst, data.data(), data.size());
|
---|
54 | GlobalUnlock(gData);
|
---|
55 | }
|
---|
56 | else {
|
---|
57 | GlobalFree(gData);
|
---|
58 | gData = NULL;
|
---|
59 | }
|
---|
60 | }
|
---|
61 |
|
---|
62 | return gData;
|
---|
63 | }
|
---|
64 |
|
---|
65 | CString
|
---|
66 | CMSWindowsClipboardBitmapConverter::toIClipboard(HANDLE data) const
|
---|
67 | {
|
---|
68 | // get datator
|
---|
69 | const char* src = (const char*)GlobalLock(data);
|
---|
70 | if (src == NULL) {
|
---|
71 | return CString();
|
---|
72 | }
|
---|
73 | UInt32 srcSize = (UInt32)GlobalSize(data);
|
---|
74 |
|
---|
75 | // check image type
|
---|
76 | const BITMAPINFO* bitmap = reinterpret_cast<const BITMAPINFO*>(src);
|
---|
77 | LOG((CLOG_INFO "bitmap: %dx%d %d", bitmap->bmiHeader.biWidth, bitmap->bmiHeader.biHeight, (int)bitmap->bmiHeader.biBitCount));
|
---|
78 | if (bitmap->bmiHeader.biPlanes == 1 &&
|
---|
79 | (bitmap->bmiHeader.biBitCount == 24 ||
|
---|
80 | bitmap->bmiHeader.biBitCount == 32) &&
|
---|
81 | bitmap->bmiHeader.biCompression == BI_RGB) {
|
---|
82 | // already in canonical form
|
---|
83 | CString image(src, srcSize);
|
---|
84 | GlobalUnlock(data);
|
---|
85 | return image;
|
---|
86 | }
|
---|
87 |
|
---|
88 | // create a destination DIB section
|
---|
89 | LOG((CLOG_INFO "convert image from: depth=%d comp=%d", bitmap->bmiHeader.biBitCount, bitmap->bmiHeader.biCompression));
|
---|
90 | void* raw;
|
---|
91 | BITMAPINFOHEADER info;
|
---|
92 | LONG w = bitmap->bmiHeader.biWidth;
|
---|
93 | LONG h = bitmap->bmiHeader.biHeight;
|
---|
94 | info.biSize = sizeof(BITMAPINFOHEADER);
|
---|
95 | info.biWidth = w;
|
---|
96 | info.biHeight = h;
|
---|
97 | info.biPlanes = 1;
|
---|
98 | info.biBitCount = 32;
|
---|
99 | info.biCompression = BI_RGB;
|
---|
100 | info.biSizeImage = 0;
|
---|
101 | info.biXPelsPerMeter = 1000;
|
---|
102 | info.biYPelsPerMeter = 1000;
|
---|
103 | info.biClrUsed = 0;
|
---|
104 | info.biClrImportant = 0;
|
---|
105 | HDC dc = GetDC(NULL);
|
---|
106 | HBITMAP dst = CreateDIBSection(dc, (BITMAPINFO*)&info,
|
---|
107 | DIB_RGB_COLORS, &raw, NULL, 0);
|
---|
108 |
|
---|
109 | // find the start of the pixel data
|
---|
110 | const char* srcBits = (const char*)bitmap + bitmap->bmiHeader.biSize;
|
---|
111 | if (bitmap->bmiHeader.biBitCount >= 16) {
|
---|
112 | if (bitmap->bmiHeader.biCompression == BI_BITFIELDS &&
|
---|
113 | (bitmap->bmiHeader.biBitCount == 16 ||
|
---|
114 | bitmap->bmiHeader.biBitCount == 32)) {
|
---|
115 | srcBits += 3 * sizeof(DWORD);
|
---|
116 | }
|
---|
117 | }
|
---|
118 | else if (bitmap->bmiHeader.biClrUsed != 0) {
|
---|
119 | srcBits += bitmap->bmiHeader.biClrUsed * sizeof(RGBQUAD);
|
---|
120 | }
|
---|
121 | else {
|
---|
122 | srcBits += (1 << bitmap->bmiHeader.biBitCount) * sizeof(RGBQUAD);
|
---|
123 | }
|
---|
124 |
|
---|
125 | // copy source image to destination image
|
---|
126 | HDC dstDC = CreateCompatibleDC(dc);
|
---|
127 | HGDIOBJ oldBitmap = SelectObject(dstDC, dst);
|
---|
128 | SetDIBitsToDevice(dstDC, 0, 0, w, h, 0, 0, 0, h,
|
---|
129 | srcBits, bitmap, DIB_RGB_COLORS);
|
---|
130 | SelectObject(dstDC, oldBitmap);
|
---|
131 | DeleteDC(dstDC);
|
---|
132 | GdiFlush();
|
---|
133 |
|
---|
134 | // extract data
|
---|
135 | CString image((const char*)&info, info.biSize);
|
---|
136 | image.append((const char*)raw, 4 * w * h);
|
---|
137 |
|
---|
138 | // clean up GDI
|
---|
139 | DeleteObject(dst);
|
---|
140 | ReleaseDC(NULL, dc);
|
---|
141 |
|
---|
142 | // release handle
|
---|
143 | GlobalUnlock(data);
|
---|
144 |
|
---|
145 | return image;
|
---|
146 | }
|
---|