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

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

createControls & OSLibEnableWindow bugfixes + LookupIconIdFromDirectory(Ex) port)

File size: 9.8 KB
Line 
1/* $Id: winicon.cpp,v 1.3 1999-11-14 16:35:58 sandervl Exp $ */
2/*
3 * Win32 Icon Code for OS/2
4 *
5 *
6 * Copyright 1998 Sander van Leeuwen (sandervl@xs4all.nl)
7 *
8 * LookupIconIdFromDirectory(Ex) (+help functions) ported from Wine (991031)
9 *
10 * Copyright 1995 Alexandre Julliard
11 * 1996 Martin Von Loewis
12 * 1997 Alex Korobka
13 * 1998 Turchanov Sergey
14 *
15 * Project Odin Software License can be found in LICENSE.TXT
16 *
17 */
18#include <os2win.h>
19#include <winicon.h>
20#include <win\cursoricon.h>
21
22//******************************************************************************
23//******************************************************************************
24HICON WIN32API CreateIcon( HINSTANCE arg1, INT arg2, INT arg3, BYTE arg4, BYTE arg5, LPCVOID arg6, LPCVOID arg7)
25{
26#ifdef DEBUG
27 WriteLog("USER32: CreateIcon\n");
28#endif
29 return O32_CreateIcon(arg1, arg2, arg3, arg4, arg5, (const BYTE *)arg6, (const BYTE *)arg7);
30}
31//******************************************************************************
32//ASSERT dwVer == win31 (ok according to SDK docs)
33//******************************************************************************
34HICON WIN32API CreateIconFromResource(PBYTE presbits, UINT dwResSize,
35 BOOL fIcon, DWORD dwVer)
36{
37 HICON hicon;
38 DWORD OS2ResSize = 0;
39 PBYTE OS2Icon = ConvertWin32Icon(presbits, dwResSize, &OS2ResSize);
40
41 hicon = O32_CreateIconFromResource(OS2Icon, OS2ResSize, fIcon, dwVer);
42#ifdef DEBUG
43 WriteLog("USER32: CreateIconFromResource returned %X (%X)\n", hicon, GetLastError());
44#endif
45 if(OS2Icon)
46 FreeIcon(OS2Icon);
47
48 return(hicon);
49}
50//******************************************************************************
51//******************************************************************************
52HICON WIN32API CreateIconFromResourceEx(PBYTE presbits, UINT dwResSize,
53 BOOL fIcon, DWORD dwVer,
54 int cxDesired, int cyDesired,
55 UINT Flags)
56{
57#ifdef DEBUG
58 WriteLog("USER32: CreateIconFromResourceEx %X %d %d %X %d %d %X, not completely supported!\n", presbits, dwResSize, fIcon, dwVer, cxDesired, cyDesired, Flags);
59#endif
60 return CreateIconFromResource(presbits, dwResSize, fIcon, dwVer);
61}
62//******************************************************************************
63//******************************************************************************
64HICON WIN32API CreateIconIndirect(LPICONINFO pIcon)
65{
66 HICON hIcon;
67 HDC hdcSrc, hdcDst;
68
69 dprintf(("USER32: CreateIconIndirect\n"));
70 if(pIcon->hbmMask && pIcon->hbmColor)
71 {
72 ICONINFO iconinfo;
73 SIZE bmpsize;
74
75 iconinfo = *pIcon;
76 if(GetBitmapDimensionEx(pIcon->hbmColor, &bmpsize) == FALSE) {
77 return 0;
78 }
79 //if there's a color bitmap, the mask bitmap contains only the AND bits
80 //Open32 calls WinCreatePointerIndirect which expects AND & XOR bits
81 //To solve this we create a bitmap that's 2x height of the mask, copy
82 //the AND bits and set the XOR bits to 0
83 hdcSrc = CreateCompatibleDC(0);
84 hdcDst = CreateCompatibleDC(0);
85
86 iconinfo.hbmMask = CreateCompatibleBitmap (hdcDst, bmpsize.cx, bmpsize.cy*2);
87 SelectObject (hdcDst, iconinfo.hbmMask);
88 SelectObject (hdcSrc, pIcon->hbmMask);
89 BitBlt (hdcDst, 0, 0, bmpsize.cx, bmpsize.cy,
90 hdcSrc, bmpsize.cx, 0, SRCCOPY);
91 PatBlt (hdcDst, bmpsize.cx, bmpsize.cy, bmpsize.cx, bmpsize.cy, BLACKNESS);
92
93 hIcon = O32_CreateIconIndirect(&iconinfo);
94
95 DeleteObject(iconinfo.hbmMask);
96 DeleteDC(hdcSrc);
97 DeleteDC(hdcDst);
98
99 return hIcon;
100 }
101 hIcon = O32_CreateIconIndirect(pIcon);
102 if(hIcon == 0) {
103 dprintf(("CreateIconIndirect %d (%d,%d) %x %x failed with %x", pIcon->fIcon, pIcon->xHotspot, pIcon->yHotspot, pIcon->hbmMask, pIcon->hbmColor, GetLastError()));
104 }
105 return hIcon;
106}
107//******************************************************************************
108//******************************************************************************
109BOOL WIN32API DestroyIcon( HICON arg1)
110{
111#ifdef DEBUG
112 WriteLog("USER32: DestroyIcon\n");
113#endif
114 return O32_DestroyIcon(arg1);
115}
116//******************************************************************************
117//******************************************************************************
118HICON WIN32API CopyIcon( HICON arg1)
119{
120#ifdef DEBUG
121 WriteLog("USER32: CopyIcon\n");
122#endif
123 return O32_CopyIcon(arg1);
124}
125//******************************************************************************
126//******************************************************************************
127BOOL WIN32API GetIconInfo( HICON arg1, LPICONINFO arg2)
128{
129#ifdef DEBUG
130 WriteLog("USER32: GetIconInfo\n");
131#endif
132 return O32_GetIconInfo(arg1, arg2);
133}
134/**********************************************************************
135 * CURSORICON_FindBestIcon
136 *
137 * Find the icon closest to the requested size and number of colors.
138 */
139static CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
140 int height, int colors )
141{
142 int i;
143 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
144 UINT iTotalDiff, iXDiff=0, iYDiff=0, iColorDiff;
145 UINT iTempXDiff, iTempYDiff, iTempColorDiff;
146
147 if (dir->idCount < 1)
148 {
149 dprintf(("Empty directory!\n" ));
150 return NULL;
151 }
152 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
153
154 /* Find Best Fit */
155 iTotalDiff = 0xFFFFFFFF;
156 iColorDiff = 0xFFFFFFFF;
157 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
158 {
159 iTempXDiff = abs(width - entry->ResInfo.icon.bWidth);
160 iTempYDiff = abs(height - entry->ResInfo.icon.bHeight);
161
162 if(iTotalDiff > (iTempXDiff + iTempYDiff))
163 {
164 iXDiff = iTempXDiff;
165 iYDiff = iTempYDiff;
166 iTotalDiff = iXDiff + iYDiff;
167 }
168 }
169
170 /* Find Best Colors for Best Fit */
171 for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
172 {
173 if(abs(width - entry->ResInfo.icon.bWidth) == iXDiff &&
174 abs(height - entry->ResInfo.icon.bHeight) == iYDiff)
175 {
176 iTempColorDiff = abs(colors - entry->ResInfo.icon.bColorCount);
177 if(iColorDiff > iTempColorDiff)
178 {
179 bestEntry = entry;
180 iColorDiff = iTempColorDiff;
181 }
182 }
183 }
184
185 return bestEntry;
186}
187
188
189/**********************************************************************
190 * CURSORICON_FindBestCursor
191 *
192 * Find the cursor closest to the requested size.
193 * FIXME: parameter 'color' ignored and entries with more than 1 bpp
194 * ignored too
195 */
196static CURSORICONDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
197 int width, int height, int color)
198{
199 int i, maxwidth, maxheight;
200 CURSORICONDIRENTRY *entry, *bestEntry = NULL;
201
202 if (dir->idCount < 1)
203 {
204 dprintf(("Empty directory!\n" ));
205 return NULL;
206 }
207 if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
208
209 /* Double height to account for AND and XOR masks */
210
211 height *= 2;
212
213 /* First find the largest one smaller than or equal to the requested size*/
214
215 maxwidth = maxheight = 0;
216 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
217 if ((entry->ResInfo.cursor.wWidth <= width) && (entry->ResInfo.cursor.wHeight <= height) &&
218 (entry->ResInfo.cursor.wWidth > maxwidth) && (entry->ResInfo.cursor.wHeight > maxheight) &&
219 (entry->wBitCount == 1))
220 {
221 bestEntry = entry;
222 maxwidth = entry->ResInfo.cursor.wWidth;
223 maxheight = entry->ResInfo.cursor.wHeight;
224 }
225 if (bestEntry) return bestEntry;
226
227 /* Now find the smallest one larger than the requested size */
228
229 maxwidth = maxheight = 255;
230 for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
231 if ((entry->ResInfo.cursor.wWidth < maxwidth) && (entry->ResInfo.cursor.wHeight < maxheight) &&
232 (entry->wBitCount == 1))
233 {
234 bestEntry = entry;
235 maxwidth = entry->ResInfo.cursor.wWidth;
236 maxheight = entry->ResInfo.cursor.wHeight;
237 }
238
239 return bestEntry;
240}
241/**********************************************************************
242 * LookupIconIdFromDirectoryEx16 (USER.364)
243 *
244 * FIXME: exact parameter sizes
245 */
246INT WIN32API LookupIconIdFromDirectoryEx(LPBYTE xdir, BOOL bIcon,
247 INT width, INT height, UINT cFlag )
248{
249 CURSORICONDIR *dir = (CURSORICONDIR*)xdir;
250 UINT retVal = 0;
251
252 dprintf(("LookupIconIdFromDirectoryEx %x %d (%d,%d)", xdir, bIcon, width, height));
253 if( dir && !dir->idReserved && (dir->idType & 3) )
254 {
255 CURSORICONDIRENTRY* entry;
256 HDC hdc;
257 UINT palEnts;
258 int colors;
259 hdc = GetDC(0);
260 palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
261 if (palEnts == 0)
262 palEnts = 256;
263 colors = (cFlag & LR_MONOCHROME) ? 2 : palEnts;
264
265 ReleaseDC(0, hdc);
266
267 if( bIcon )
268 entry = CURSORICON_FindBestIcon( dir, width, height, colors );
269 else
270 entry = CURSORICON_FindBestCursor( dir, width, height, 1);
271
272 if( entry ) retVal = entry->wResId;
273 }
274 else dprintf(("invalid resource directory\n"));
275 return retVal;
276}
277/**********************************************************************
278 * LookupIconIdFromDirectory (USER32.379)
279 */
280INT WIN32API LookupIconIdFromDirectory( LPBYTE dir, BOOL bIcon )
281{
282 return LookupIconIdFromDirectoryEx( dir, bIcon,
283 bIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
284 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME );
285}
286//******************************************************************************
287//******************************************************************************
Note: See TracBrowser for help on using the repository browser.