Skip to content

Commit 7924c66

Browse files
Fixed clipboard handling for bitmaps/metadata/etc., code by Nakashima Tomoaki (thanks!)
1 parent 93401e8 commit 7924c66

File tree

5 files changed

+333
-51
lines changed

5 files changed

+333
-51
lines changed

clipboard.c

Lines changed: 311 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,311 @@
1+
/*
2+
* Copyright (C) 1996-2003 by Nakashima Tomoaki. All rights reserved.
3+
* http://www.nakka.com/
4+
5+
*/
6+
7+
#include "stdafx.h"
8+
#include "clipboard.h"
9+
10+
/*
11+
* bitmap_to_dib - ビットマップをDIBに変換
12+
*/
13+
static BYTE *bitmap_to_dib(const HBITMAP hbmp, size_t *size)
14+
{
15+
HDC hdc;
16+
BITMAP bmp;
17+
BYTE *ret; // BITMAPINFO
18+
DWORD biComp = BI_RGB;
19+
size_t len;
20+
size_t hsize;
21+
DWORD err;
22+
int color_bit = 0;
23+
24+
// BITMAP情報取得--Information acquisition
25+
if(GetObject(hbmp, sizeof(BITMAP), &bmp) == 0) {
26+
return NULL;
27+
}
28+
switch(bmp.bmBitsPixel) {
29+
case 1:
30+
color_bit = 2;
31+
break;
32+
case 4:
33+
color_bit = 16;
34+
break;
35+
case 8:
36+
color_bit = 256;
37+
break;
38+
case 16:
39+
case 32:
40+
color_bit = 3;
41+
biComp = BI_BITFIELDS;
42+
break;
43+
}
44+
len = (((bmp.bmWidth * bmp.bmBitsPixel) / 8) % 4)
45+
? ((((bmp.bmWidth * bmp.bmBitsPixel) / 8) / 4) + 1) * 4
46+
: (bmp.bmWidth * bmp.bmBitsPixel) / 8;
47+
48+
if((hdc = GetDC(NULL)) == NULL) {
49+
return NULL;
50+
}
51+
52+
hsize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * color_bit;
53+
if((ret = malloc(hsize + len * bmp.bmHeight)) == NULL) {
54+
err = GetLastError();
55+
ReleaseDC(NULL, hdc);
56+
SetLastError(err);
57+
return NULL;
58+
}
59+
// DIBヘッダ-- DIB header
60+
ZeroMemory(ret, hsize);
61+
((BITMAPINFO *)ret)->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
62+
((BITMAPINFO *)ret)->bmiHeader.biWidth = bmp.bmWidth;
63+
((BITMAPINFO *)ret)->bmiHeader.biHeight = bmp.bmHeight;
64+
((BITMAPINFO *)ret)->bmiHeader.biPlanes = 1;
65+
((BITMAPINFO *)ret)->bmiHeader.biBitCount = bmp.bmBitsPixel;
66+
((BITMAPINFO *)ret)->bmiHeader.biCompression = biComp;
67+
((BITMAPINFO *)ret)->bmiHeader.biSizeImage = len * bmp.bmHeight;
68+
((BITMAPINFO *)ret)->bmiHeader.biClrImportant = 0;
69+
70+
// DIB取得-- DIB to obtain
71+
if(GetDIBits(hdc, hbmp, 0, bmp.bmHeight, ret + hsize, (BITMAPINFO *)ret, DIB_RGB_COLORS) == 0) {
72+
err = GetLastError();
73+
ReleaseDC(NULL, hdc);
74+
free(ret);
75+
SetLastError(err);
76+
return NULL;
77+
}
78+
ReleaseDC(NULL, hdc);
79+
*size = hsize + len * bmp.bmHeight;
80+
return ret;
81+
}
82+
83+
/*
84+
* dib_to_bitmap - DIBをビットマップに変換-- Convert a bitmap DIB
85+
*/
86+
static HBITMAP dib_to_bitmap(const BYTE *dib)
87+
{
88+
HDC hdc;
89+
HBITMAP ret;
90+
size_t hsize;
91+
DWORD err;
92+
int color_bit;
93+
94+
if((hdc = GetDC(NULL)) == NULL) {
95+
return NULL;
96+
}
97+
98+
// ヘッダサイズ取得-- Header size acquisition
99+
if((color_bit = ((BITMAPINFOHEADER *)dib)->biClrUsed) == 0) {
100+
color_bit = ((BITMAPINFOHEADER *)dib)->biPlanes * ((BITMAPINFOHEADER *)dib)->biBitCount;
101+
if(color_bit == 1) {
102+
color_bit = 2;
103+
}
104+
else if(color_bit <= 4) {
105+
color_bit = 16;
106+
}
107+
else if(color_bit <= 8) {
108+
color_bit = 256;
109+
}
110+
else if(color_bit <= 16) {
111+
color_bit = 3;
112+
}
113+
else if(color_bit <= 24) {
114+
color_bit = 0;
115+
}
116+
else {
117+
color_bit = 3;
118+
}
119+
}
120+
hsize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * color_bit;
121+
122+
// ビットマップに変換-- Convert to bitmap
123+
ret = CreateDIBitmap(hdc, (BITMAPINFOHEADER *)dib, CBM_INIT, dib + hsize, (BITMAPINFO *)dib, DIB_RGB_COLORS);
124+
if(ret == NULL) {
125+
err = GetLastError();
126+
ReleaseDC(NULL, hdc);
127+
SetLastError(err);
128+
return NULL;
129+
}
130+
ReleaseDC(NULL, hdc);
131+
return ret;
132+
}
133+
134+
/*
135+
* clipboard_copy_data - クリップボードデータのコピーを作成-- Create a copy of the clipboard data
136+
*/
137+
HANDLE clipboard_copy_data(const UINT format, const HANDLE data, size_t *ret_size)
138+
{
139+
HANDLE ret = NULL;
140+
BYTE *from_mem, *to_mem;
141+
LOGPALETTE *lpal;
142+
WORD pcnt;
143+
144+
if(data == NULL) {
145+
return NULL;
146+
}
147+
148+
switch(format) {
149+
case CF_PALETTE:
150+
// パレット--Palette
151+
pcnt = 0;
152+
if(GetObject(data, sizeof(WORD), &pcnt) == 0) {
153+
return NULL;
154+
}
155+
if((lpal = malloc(sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * pcnt))) == NULL) {
156+
return NULL;
157+
}
158+
lpal->palVersion = 0x300;
159+
lpal->palNumEntries = pcnt;
160+
if(GetPaletteEntries(data, 0, pcnt, lpal->palPalEntry) == 0) {
161+
free(lpal);
162+
return NULL;
163+
}
164+
165+
ret = CreatePalette(lpal);
166+
*ret_size = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * pcnt);
167+
168+
free(lpal);
169+
break;
170+
171+
case CF_DSPBITMAP:
172+
case CF_BITMAP:
173+
// ビットマップ--Bitmap
174+
if((to_mem = bitmap_to_dib(data, ret_size)) == NULL) {
175+
return NULL;
176+
}
177+
ret = dib_to_bitmap(to_mem);
178+
free(to_mem);
179+
break;
180+
181+
case CF_OWNERDISPLAY:
182+
*ret_size = 0;
183+
break;
184+
185+
case CF_DSPMETAFILEPICT:
186+
case CF_METAFILEPICT:
187+
// コピー元ロック-- Source rock
188+
if((from_mem = GlobalLock(data)) == NULL) {
189+
return NULL;
190+
}
191+
// メタファイル-- Metafile
192+
if((ret = GlobalAlloc(GHND, sizeof(METAFILEPICT))) == NULL) {
193+
GlobalUnlock(data);
194+
return NULL;
195+
}
196+
// コピー先ロック-- Destination lock
197+
if((to_mem = GlobalLock(ret)) == NULL) {
198+
GlobalFree(ret);
199+
GlobalUnlock(data);
200+
return NULL;
201+
}
202+
CopyMemory(to_mem, from_mem, sizeof(METAFILEPICT));
203+
if((((METAFILEPICT *)to_mem)->hMF = CopyMetaFile(((METAFILEPICT *)from_mem)->hMF, NULL)) != NULL) {
204+
*ret_size = sizeof(METAFILEPICT) + GetMetaFileBitsEx(((METAFILEPICT *)to_mem)->hMF, 0, NULL);
205+
}
206+
// ロック解除-- Unlock
207+
GlobalUnlock(ret);
208+
GlobalUnlock(data);
209+
break;
210+
211+
case CF_DSPENHMETAFILE:
212+
case CF_ENHMETAFILE:
213+
// 拡張メタファイル-- Enhanced Metafiles
214+
if((ret = CopyEnhMetaFile(data, NULL)) != NULL) {
215+
*ret_size = GetEnhMetaFileBits(ret, 0, NULL);
216+
}
217+
break;
218+
219+
default:
220+
// その他-- Other
221+
// メモリチェック-- Memory check
222+
//if(IsBadReadPtr(data, 1) == TRUE) {
223+
// return NULL;
224+
//}
225+
// サイズ取得-- Size acquisition
226+
if((*ret_size = GlobalSize(data)) == 0) {
227+
return NULL;
228+
}
229+
// コピー元ロック-- Source rock
230+
if((from_mem = GlobalLock(data)) == NULL) {
231+
return NULL;
232+
}
233+
234+
// コピー先確保-- Copy to ensure
235+
if((ret = GlobalAlloc(GHND, *ret_size)) == NULL) {
236+
GlobalUnlock(data);
237+
return NULL;
238+
}
239+
// コピー先ロック-- Destination lock
240+
if((to_mem = GlobalLock(ret)) == NULL) {
241+
GlobalFree(ret);
242+
GlobalUnlock(data);
243+
return NULL;
244+
}
245+
246+
// コピー-- Copy
247+
CopyMemory(to_mem, from_mem, *ret_size);
248+
249+
// ロック解除-- Unlock
250+
GlobalUnlock(ret);
251+
GlobalUnlock(data);
252+
break;
253+
}
254+
return ret;
255+
}
256+
257+
/*
258+
* clipboard_free_data - クリップボード形式毎のメモリの解放 --
259+
Freeing memory for each clipboard format
260+
*/
261+
BOOL clipboard_free_data(const UINT format, HANDLE data)
262+
{
263+
BOOL ret = FALSE;
264+
BYTE *mem;
265+
266+
if(data == NULL) {
267+
return TRUE;
268+
}
269+
270+
switch(format) {
271+
case CF_PALETTE:
272+
// パレット-- Palette
273+
ret = DeleteObject((HGDIOBJ)data);
274+
break;
275+
276+
case CF_DSPBITMAP:
277+
case CF_BITMAP:
278+
// ビットマップ-- Bitmap
279+
ret = DeleteObject((HGDIOBJ)data);
280+
break;
281+
282+
case CF_OWNERDISPLAY:
283+
break;
284+
285+
case CF_DSPMETAFILEPICT:
286+
case CF_METAFILEPICT:
287+
// メタファイル-- Metafile
288+
if((mem = GlobalLock(data)) != NULL) {
289+
DeleteMetaFile(((METAFILEPICT *)mem)->hMF);
290+
GlobalUnlock(data);
291+
}
292+
if(GlobalFree((HGLOBAL)data) == NULL) {
293+
ret = TRUE;
294+
}
295+
break;
296+
297+
case CF_DSPENHMETAFILE:
298+
case CF_ENHMETAFILE:
299+
// 拡張メタファイル-- Enhanced Metafiles
300+
ret = DeleteEnhMetaFile((HENHMETAFILE)data);
301+
break;
302+
303+
default:
304+
// その他-- Other
305+
if(GlobalFree((HGLOBAL)data) == NULL) {
306+
ret = TRUE;
307+
}
308+
break;
309+
}
310+
return ret;
311+
}

clipboard.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#pragma once
2+
3+
HANDLE clipboard_copy_data(const UINT format, const HANDLE data, size_t *ret_size);
4+
BOOL clipboard_free_data(const UINT format, HANDLE data);

0 commit comments

Comments
 (0)