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

Last change on this file since 2803 was 2803, checked in by sandervl, 26 years ago

Added new logging feature

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