source: trunk/src/user32/winicon.cpp@ 3209

Last change on this file since 3209 was 3209, checked in by sandervl, 25 years ago

replaced writelog calls

File size: 16.0 KB
Line 
1/* $Id: winicon.cpp,v 1.10 2000-03-23 23:06:54 sandervl Exp $ */
2/*
3 * Win32 Icon Code for OS/2
4 *
5 *
6 * Copyright 1998 Sander van Leeuwen (sandervl@xs4all.nl)
7 *
8 * Parts based on Wine code (objects\bitmap.c, loader\resource.c, objects\cursoricon.c):
9 *
10 * Copyright 1993 Alexandre Julliard
11 * 1993 Robert J. Amstadt
12 * 1996 Martin Von Loewis
13 * 1997 Alex Korobka
14 * 1998 Turchanov Sergey
15 * 1998 Huw D M Davies
16 *
17 * Project Odin Software License can be found in LICENSE.TXT
18 *
19 */
20#include <os2win.h>
21#include <winicon.h>
22#include <win\cursoricon.h>
23
24#define DBG_LOCALLOG DBG_winicon
25#include "dbglocal.h"
26
27//******************************************************************************
28//******************************************************************************
29HICON WIN32API CreateIcon( HINSTANCE arg1, INT arg2, INT arg3, BYTE arg4, BYTE arg5, LPCVOID arg6, LPCVOID arg7)
30{
31 dprintf(("USER32: CreateIcon\n"));
32 return O32_CreateIcon(arg1, arg2, arg3, arg4, arg5, (const BYTE *)arg6, (const BYTE *)arg7);
33}
34//******************************************************************************
35//ASSERT dwVer == win31 (ok according to SDK docs)
36//******************************************************************************
37HICON WIN32API CreateIconFromResource(PBYTE presbits, UINT dwResSize,
38 BOOL fIcon, DWORD dwVer)
39{
40 HICON hicon;
41 DWORD OS2ResSize = 0;
42 PBYTE OS2Icon = ConvertWin32Icon(presbits, dwResSize, &OS2ResSize);
43
44 hicon = O32_CreateIconFromResource(OS2Icon, OS2ResSize, fIcon, dwVer);
45 dprintf(("USER32: CreateIconFromResource returned %X (%X)\n", hicon, GetLastError()));
46 if(OS2Icon)
47 FreeIcon(OS2Icon);
48
49 return(hicon);
50}
51//******************************************************************************
52//******************************************************************************
53HICON WIN32API CreateIconFromResourceEx(PBYTE presbits, UINT dwResSize,
54 BOOL fIcon, DWORD dwVer,
55 int cxDesired, int cyDesired,
56 UINT Flags)
57{
58 dprintf(("USER32: CreateIconFromResourceEx %X %d %d %X %d %d %X, not completely supported!\n", presbits, dwResSize, fIcon, dwVer, cxDesired, cyDesired, Flags));
59 return CreateIconFromResource(presbits, dwResSize, fIcon, dwVer);
60}
61//******************************************************************************
62//******************************************************************************
63HICON WIN32API CreateIconIndirect(LPICONINFO pIcon)
64{
65 HICON hIcon;
66 HDC hdcSrc, hdcDst;
67
68 dprintf(("USER32: CreateIconIndirect\n"));
69 if(pIcon->hbmMask && pIcon->hbmColor)
70 {
71 ICONINFO iconinfo;
72 SIZE bmpsize;
73
74 iconinfo = *pIcon;
75 if(GetBitmapDimensionEx(pIcon->hbmColor, &bmpsize) == FALSE) {
76 return 0;
77 }
78 //if there's a color bitmap, the mask bitmap contains only the AND bits
79 //Open32 calls WinCreatePointerIndirect which expects AND & XOR bits
80 //To solve this we create a bitmap that's 2x height of the mask, copy
81 //the AND bits and set the XOR bits to 0
82 hdcSrc = CreateCompatibleDC(0);
83 hdcDst = CreateCompatibleDC(0);
84
85 iconinfo.hbmMask = CreateCompatibleBitmap (hdcDst, bmpsize.cx, bmpsize.cy*2);
86 SelectObject (hdcDst, iconinfo.hbmMask);
87 SelectObject (hdcSrc, pIcon->hbmMask);
88 BitBlt (hdcDst, 0, 0, bmpsize.cx, bmpsize.cy,
89 hdcSrc, 0, 0, SRCCOPY);
90 PatBlt (hdcDst, bmpsize.cx, bmpsize.cy, bmpsize.cx, bmpsize.cy, BLACKNESS);
91
92 hIcon = O32_CreateIconIndirect(&iconinfo);
93
94 DeleteObject(iconinfo.hbmMask);
95 DeleteDC(hdcSrc);
96 DeleteDC(hdcDst);
97
98 return hIcon;
99 }
100 hIcon = O32_CreateIconIndirect(pIcon);
101 if(hIcon == 0) {
102 dprintf(("CreateIconIndirect %d (%d,%d) %x %x failed with %x", pIcon->fIcon, pIcon->xHotspot, pIcon->yHotspot, pIcon->hbmMask, pIcon->hbmColor, GetLastError()));
103 }
104 return hIcon;
105}
106//******************************************************************************
107//******************************************************************************
108HICON CreateIconIndirect(LPICONINFO pIcon, BOOL bIsIcon, int desiredX, int desiredY, DWORD flags)
109{
110 HICON hIcon;
111 HDC hdcSrc, hdcDst;
112 BITMAP bmp;
113
114 if(pIcon->hbmMask && pIcon->hbmColor)
115 {
116 ICONINFO iconinfo;
117 HBITMAP hbmOldSrc, hbmOldDst;
118
119 iconinfo = *pIcon;
120 GetObjectA(pIcon->hbmColor, sizeof(BITMAP), (LPVOID)&bmp);
121
122 //if there's a color bitmap, the mask bitmap contains only the AND bits
123 //Open32 calls WinCreatePointerIndirect which expects AND & XOR bits
124 //To solve this we create a bitmap that's 2x height of the mask, copy
125 //the AND bits and set the XOR bits to 0
126 hdcSrc = CreateCompatibleDC(0);
127 hdcDst = CreateCompatibleDC(0);
128
129 iconinfo.hbmMask = CreateCompatibleBitmap (hdcDst, desiredX, desiredY*2);
130 hbmOldDst = SelectObject (hdcDst, iconinfo.hbmMask);
131 hbmOldSrc = SelectObject (hdcSrc, pIcon->hbmMask);
132 if(desiredX != bmp.bmWidth || desiredY != bmp.bmHeight) {
133 StretchBlt(hdcDst, 0, 0, desiredX, desiredY, hdcSrc, 0, 0,
134 bmp.bmWidth, bmp.bmHeight, SRCCOPY);
135 }
136 else {
137 BitBlt (hdcDst, 0, 0, bmp.bmWidth, bmp.bmHeight,
138 hdcSrc, 0, 0, SRCCOPY);
139 }
140 PatBlt (hdcDst, desiredX, desiredY, desiredX, desiredY, BLACKNESS);
141
142 if(desiredX != bmp.bmWidth || desiredY != bmp.bmHeight) {
143 iconinfo.hbmColor = CreateCompatibleBitmap (hdcDst, desiredX, desiredY);
144 SelectObject (hdcDst, iconinfo.hbmColor);
145 SelectObject (hdcSrc, pIcon->hbmColor);
146 StretchBlt(hdcDst, 0, 0, desiredX, desiredY, hdcSrc, 0, 0,
147 bmp.bmWidth, bmp.bmHeight, SRCCOPY);
148 }
149
150 hIcon = O32_CreateIconIndirect(&iconinfo);
151
152 DeleteObject(iconinfo.hbmMask);
153 if(desiredX != bmp.bmWidth || desiredY != bmp.bmHeight) {
154 DeleteObject(iconinfo.hbmColor);
155 }
156 SelectObject (hdcDst, hbmOldDst);
157 SelectObject (hdcSrc, hbmOldSrc);
158 DeleteDC(hdcSrc);
159 DeleteDC(hdcDst);
160
161 return hIcon;
162 }
163 hIcon = O32_CreateIconIndirect(pIcon);
164 if(hIcon == 0) {
165 dprintf(("CreateIconIndirect %d (%d,%d) %x %x failed with %x", pIcon->fIcon, pIcon->xHotspot, pIcon->yHotspot, pIcon->hbmMask, pIcon->hbmColor, GetLastError()));
166 }
167 return hIcon;
168}
169//******************************************************************************
170//******************************************************************************
171BOOL WIN32API DestroyIcon( HICON hIcon)
172{
173 dprintf(("USER32: DestroyIcon %x", hIcon));
174 return O32_DestroyIcon(hIcon);
175}
176//******************************************************************************
177//******************************************************************************
178HICON WIN32API CopyIcon( HICON hIcon)
179{
180 dprintf(("USER32: CopyIcon %x", hIcon));
181 return O32_CopyIcon(hIcon);
182}
183//******************************************************************************
184//WARNING: MEMORY LEAK & DIRTY HACK TO WORK AROUND OPEN32 BUG
185//OS/2 icon masks must be twice the height of the color bitmap
186//In Windows, the mask only contains the AND data if there's a color bitmap
187//--->> We're allocating a bitmap to replace the mask bitmap, but DON'T DELETE it!
188//WARNING: DIRTY HACK TO WORK AROUND OPEN32 BUG
189//******************************************************************************
190BOOL WIN32API GetIconInfo( HICON hIcon, LPICONINFO pIconInfo)
191{
192 BOOL rc;
193 HBITMAP hbmMask, hbmOldSrc, hbmOldDst;
194 BITMAP bmp;
195
196 dprintf(("USER32: GetIconInfo %x", hIcon));
197 rc = O32_GetIconInfo(hIcon, pIconInfo);
198#if 1
199 if(rc && pIconInfo->hbmColor)
200 {
201 HDC hdcSrc, hdcDst;
202 hdcSrc = CreateCompatibleDC(0);
203 hdcDst = CreateCompatibleDC(0);
204
205 GetObjectA(pIconInfo->hbmColor, sizeof(BITMAP), (LPVOID)&bmp);
206
207 hbmMask = CreateCompatibleBitmap (hdcDst, bmp.bmWidth, bmp.bmHeight);
208 hbmOldDst = SelectObject (hdcDst, hbmMask);
209 hbmOldSrc = SelectObject (hdcSrc, pIconInfo->hbmMask);
210 BitBlt (hdcDst, 0, 0, bmp.bmWidth, bmp.bmHeight,
211 hdcSrc, 0, 0, SRCCOPY);
212
213 SelectObject(hdcDst, hbmOldDst);
214 SelectObject(hdcSrc, hbmOldSrc);
215 DeleteDC(hdcDst);
216 DeleteDC(hdcSrc);
217 DeleteObject(pIconInfo->hbmMask);
218 pIconInfo->hbmMask = hbmMask;
219 }
220#endif
221 return rc;
222}
223/**********************************************************************
224 * CURSORICON_FindBestIcon
225 *
226 * Find the icon closest to the requested size and number of colors.
227 */
228static CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
229 int height, int colors )
230{
231 int i;
232 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
233 UINT iTotalDiff, iXDiff=0, iYDiff=0, iColorDiff;
234 UINT iTempXDiff, iTempYDiff, iTempColorDiff;
235
236 if (dir->idCount < 1)
237 {
238 dprintf(("Empty directory!\n" ));
239 return NULL;
240 }
241 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
242
243 /* Find Best Fit */
244 iTotalDiff = 0xFFFFFFFF;
245 iColorDiff = 0xFFFFFFFF;
246 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
247 {
248 iTempXDiff = abs(width - entry->ResInfo.icon.bWidth);
249 iTempYDiff = abs(height - entry->ResInfo.icon.bHeight);
250
251 if(iTotalDiff > (iTempXDiff + iTempYDiff))
252 {
253 iXDiff = iTempXDiff;
254 iYDiff = iTempYDiff;
255 iTotalDiff = iXDiff + iYDiff;
256 }
257 }
258
259 /* Find Best Colors for Best Fit */
260 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
261 {
262 if(abs(width - entry->ResInfo.icon.bWidth) == iXDiff &&
263 abs(height - entry->ResInfo.icon.bHeight) == iYDiff)
264 {
265 iTempColorDiff = abs(colors - entry->ResInfo.icon.bColorCount);
266 if(iColorDiff > iTempColorDiff)
267 {
268 bestEntry = entry;
269 iColorDiff = iTempColorDiff;
270 }
271 }
272 }
273
274 return bestEntry;
275}
276
277
278/**********************************************************************
279 * CURSORICON_FindBestCursor
280 *
281 * Find the cursor closest to the requested size.
282 * FIXME: parameter 'color' ignored and entries with more than 1 bpp
283 * ignored too
284 */
285static CURSORICONDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
286 int width, int height, int color)
287{
288 int i, maxwidth, maxheight;
289 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
290
291 if (dir->idCount < 1)
292 {
293 dprintf(("Empty directory!\n" ));
294 return NULL;
295 }
296 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
297
298 /* Double height to account for AND and XOR masks */
299
300 height *= 2;
301
302 /* First find the largest one smaller than or equal to the requested size*/
303
304 maxwidth = maxheight = 0;
305 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
306 if ((entry->ResInfo.cursor.wWidth <= width) && (entry->ResInfo.cursor.wHeight <= height) &&
307 (entry->ResInfo.cursor.wWidth > maxwidth) && (entry->ResInfo.cursor.wHeight > maxheight) &&
308 (entry->wBitCount == 1))
309 {
310 bestEntry = entry;
311 maxwidth = entry->ResInfo.cursor.wWidth;
312 maxheight = entry->ResInfo.cursor.wHeight;
313 }
314 if (bestEntry) return bestEntry;
315
316 /* Now find the smallest one larger than the requested size */
317
318 maxwidth = maxheight = 255;
319 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
320 if ((entry->ResInfo.cursor.wWidth < maxwidth) && (entry->ResInfo.cursor.wHeight < maxheight) &&
321 (entry->wBitCount == 1))
322 {
323 bestEntry = entry;
324 maxwidth = entry->ResInfo.cursor.wWidth;
325 maxheight = entry->ResInfo.cursor.wHeight;
326 }
327
328 return bestEntry;
329}
330/**********************************************************************
331 * LookupIconIdFromDirectoryEx16 (USER.364)
332 *
333 * FIXME: exact parameter sizes
334 */
335INT WIN32API LookupIconIdFromDirectoryEx(LPBYTE xdir, BOOL bIcon,
336 INT width, INT height, UINT cFlag )
337{
338 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
339 UINT retVal = 0;
340
341 dprintf(("LookupIconIdFromDirectoryEx %x %d (%d,%d)", xdir, bIcon, width, height));
342 if( dir && !dir->idReserved && (dir->idType & 3) )
343 {
344 CURSORICONDIRENTRY* entry;
345 HDC hdc;
346 UINT palEnts;
347 int colors;
348 hdc = GetDC(0);
349 palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
350 if (palEnts == 0)
351 palEnts = 256;
352 colors = (cFlag & LR_MONOCHROME) ? 2 : palEnts;
353
354 ReleaseDC(0, hdc);
355
356 if( bIcon )
357 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
358 else
359 entry = CURSORICON_FindBestCursor( dir, width, height, 1);
360
361 if( entry ) retVal = entry->wResId;
362 }
363 else dprintf(("invalid resource directory\n"));
364 return retVal;
365}
366/**********************************************************************
367 * LookupIconIdFromDirectory (USER32.379)
368 */
369INT WIN32API LookupIconIdFromDirectory( LPBYTE dir, BOOL bIcon )
370{
371 return LookupIconIdFromDirectoryEx( dir, bIcon,
372 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
373 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
374}
375/*************************************************************************
376 * CURSORICON_ExtCopy
377 *
378 * Copies an Image from the Cache if LR_COPYFROMRESOURCE is specified
379 *
380 * PARAMS
381 * Handle [I] handle to an Image
382 * nType [I] Type of Handle (IMAGE_CURSOR | IMAGE_ICON)
383 * iDesiredCX [I] The Desired width of the Image
384 * iDesiredCY [I] The desired height of the Image
385 * nFlags [I] The flags from CopyImage
386 *
387 * RETURNS
388 * Success: The new handle of the Image
389 *
390 * NOTES
391 * LR_COPYDELETEORG and LR_MONOCHROME are currently not implemented.
392 * LR_MONOCHROME should be implemented by CURSORICON_CreateFromResource.
393 * LR_COPYFROMRESOURCE will only work if the Image is in the Cache.
394 *
395 *
396 * TODO: LR_COPYFROMRESOURCE doesn't work. Uses supplied icon instead
397 *
398 */
399HGLOBAL CopyCursorIcon(HGLOBAL Handle, UINT nType,
400 INT iDesiredCX, INT iDesiredCY,
401 UINT nFlags)
402{
403 HGLOBAL hNew=0;
404 BOOL bIsIcon = (nType == IMAGE_ICON);
405
406 if(Handle == 0)
407 {
408 return 0;
409 }
410
411 /* Best Fit or Monochrome */
412 if(!bIsIcon || (nFlags & LR_COPYFROMRESOURCE
413 && (iDesiredCX > 0 || iDesiredCY > 0))
414 || nFlags & LR_MONOCHROME)
415 {
416 LPBYTE pBits;
417 HANDLE hMem;
418 HRSRC hRsrc;
419 DWORD dwBytesInRes;
420 WORD wResId;
421 CURSORICONDIR *pDir;
422 CURSORICONDIRENTRY *pDirEntry;
423
424 /* Completing iDesiredCX CY for Monochrome Bitmaps if needed
425 */
426 if(((nFlags & LR_MONOCHROME) && !(nFlags & LR_COPYFROMRESOURCE))
427 || (iDesiredCX == 0 && iDesiredCY == 0))
428 {
429 iDesiredCY = GetSystemMetrics(bIsIcon ?
430 SM_CYICON : SM_CYCURSOR);
431 iDesiredCX = GetSystemMetrics(bIsIcon ?
432 SM_CXICON : SM_CXCURSOR);
433 }
434
435 /* Create a New Icon with the proper dimension
436 */
437 ICONINFO iconinfo;
438
439 GetIconInfo(Handle, &iconinfo);
440 hNew = CreateIconIndirect(&iconinfo, bIsIcon, iDesiredCX, iDesiredCY, nFlags);
441 }
442 else
443 {
444 if(bIsIcon) {
445 return CopyIcon(Handle);
446 }
447 else return CopyCursor(Handle);
448 }
449 return hNew;
450}
451//******************************************************************************
452//******************************************************************************
Note: See TracBrowser for help on using the repository browser.