Changeset 4573 for trunk/src/user32/winicon.cpp
- Timestamp:
- Nov 9, 2000, 7:15:23 PM (25 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/user32/winicon.cpp
r3209 r4573 1 /* $Id: winicon.cpp,v 1.1 0 2000-03-23 23:06:54sandervl Exp $ */1 /* $Id: winicon.cpp,v 1.11 2000-11-09 18:15:23 sandervl Exp $ */ 2 2 /* 3 3 * Win32 Icon Code for OS/2 4 4 * 5 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):6 * Copyright 1998 Sander van Leeuwen (sandervl@xs4all.nl) (OS/2 Port) 7 * 8 * Based on Wine code (objects\bitmap.c, loader\resource.c, objects\cursoricon.c): 9 9 * 10 10 * Copyright 1993 Alexandre Julliard … … 19 19 */ 20 20 #include <os2win.h> 21 #include <stdio.h> 22 #include <string.h> 21 23 #include <winicon.h> 22 24 #include <win\cursoricon.h> 23 24 #define DBG_LOCALLOG DBG_winicon 25 #include "dib.h" 26 #include <heapstring.h> 27 #include <win\virtual.h> 28 #include "initterm.h" 29 30 #define DBG_LOCALLOG DBG_winicon 25 31 #include "dbglocal.h" 26 32 33 static WORD ICON_HOTSPOT = 0x4242; 34 35 static HGLOBAL CURSORICON_CreateFromResource( HINSTANCE hInstance, HGLOBAL hObj, LPBYTE bits, 36 UINT cbSize, BOOL bIcon, DWORD dwVersion, 37 INT width, INT height, UINT loadflags ); 38 static HGLOBAL CURSORICON_Copy( HINSTANCE hInstance, HGLOBAL handle ); 39 static CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width, 40 int height, int colors ); 41 static CURSORICONDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir, 42 int width, int height, int color); 43 BOOL CURSORICON_SimulateLoadingFromResourceW( LPWSTR filename, BOOL fCursor, 44 CURSORICONDIR **res, LPBYTE **ptr); 45 46 /*********************************************************************** 47 * CreateIcon (USER32.75) 48 */ 49 HICON WIN32API CreateIcon(HINSTANCE hInstance, INT nWidth, 50 INT nHeight, BYTE bPlanes, BYTE bBitsPixel, 51 LPCVOID lpANDbits, LPCVOID lpXORbits ) 52 { 53 CURSORICONINFO info; 54 55 dprintf(("USER32: CreateIcon (%d,%d), %d, %x, %x", nWidth, nHeight, bPlanes * bBitsPixel, lpXORbits, lpANDbits)); 56 57 info.ptHotSpot.x = ICON_HOTSPOT; 58 info.ptHotSpot.y = ICON_HOTSPOT; 59 info.nWidth = nWidth; 60 info.nHeight = nHeight; 61 info.nWidthBytes = 0; 62 info.bPlanes = bPlanes; 63 info.bBitsPerPixel = bBitsPixel; 64 65 return CreateCursorIconIndirect(0, &info, lpANDbits, lpXORbits); 66 } 67 /********************************************************************** 68 * CreateIconFromResource (USER32.76) 69 */ 70 HICON WIN32API CreateIconFromResource(LPBYTE bits, UINT cbSize, 71 BOOL bIcon, DWORD dwVersion) 72 { 73 return CreateIconFromResourceEx( bits, cbSize, bIcon, dwVersion, 0,0,0); 74 } 27 75 //****************************************************************************** 28 76 //****************************************************************************** 29 HICON 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 //****************************************************************************** 37 HICON 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 //****************************************************************************** 53 HICON 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 //****************************************************************************** 63 HICON 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 //****************************************************************************** 108 HICON 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; 77 HICON WIN32API CreateIconFromResourceEx(LPBYTE bits, UINT cbSize, 78 BOOL bIcon, DWORD dwVersion, 79 INT width, INT height, 80 UINT cFlag ) 81 { 82 dprintf(("USER32: CreateIconFromResourceEx %X %d %d %X %d %d %X,", bits, cbSize, bIcon, dwVersion, width, height, cFlag)); 83 return CURSORICON_CreateFromResource(0, 0, bits, cbSize, bIcon, dwVersion, width, height, cFlag ); 84 } 85 /********************************************************************** 86 * CreateIconIndirect (USER32.78) 87 */ 88 HICON WINAPI CreateIconIndirect(ICONINFO *iconinfo) 89 { 90 BITMAP bmpXor,bmpAnd; 91 HICON hObj; 92 int sizeXor,sizeAnd; 93 94 dprintf(("USER32: CreateIconIndirect %x", iconinfo)); 95 96 GetObjectA( iconinfo->hbmColor, sizeof(bmpXor), &bmpXor ); 97 GetObjectA( iconinfo->hbmMask, sizeof(bmpAnd), &bmpAnd ); 98 99 sizeXor = bmpXor.bmHeight * bmpXor.bmWidthBytes; 100 sizeAnd = bmpAnd.bmHeight * bmpAnd.bmWidthBytes; 101 102 hObj = GlobalAlloc( GMEM_MOVEABLE, sizeof(CURSORICONINFO) + sizeXor + sizeAnd ); 103 if (hObj) 104 { 105 CURSORICONINFO *info; 106 107 info = (CURSORICONINFO *)GlobalLock( hObj ); 108 109 /* If we are creating an icon, the hotspot is unused */ 110 if (iconinfo->fIcon) 111 { 112 info->ptHotSpot.x = ICON_HOTSPOT; 113 info->ptHotSpot.y = ICON_HOTSPOT; 114 } 115 else 116 { 117 info->ptHotSpot.x = iconinfo->xHotspot; 118 info->ptHotSpot.y = iconinfo->yHotspot; 119 } 120 121 info->nWidth = bmpXor.bmWidth; 122 info->nHeight = bmpXor.bmHeight; 123 info->nWidthBytes = bmpXor.bmWidthBytes; 124 info->bPlanes = bmpXor.bmPlanes; 125 info->bBitsPerPixel = bmpXor.bmBitsPixel; 126 127 /* Transfer the bitmap bits to the CURSORICONINFO structure */ 128 GetBitmapBits( iconinfo->hbmMask ,sizeAnd,(char*)(info + 1) ); 129 GetBitmapBits( iconinfo->hbmColor,sizeXor,(char*)(info + 1) +sizeAnd); 130 GlobalUnlock(hObj); 131 } 132 else { 133 dprintf(("ERROR: CreateIconIndirect GlobalAlloc failed!!")); 134 } 135 return hObj; 168 136 } 169 137 //****************************************************************************** … … 172 140 { 173 141 dprintf(("USER32: DestroyIcon %x", hIcon)); 174 return O32_DestroyIcon(hIcon);142 return CURSORICON_Destroy( hIcon, 0 ); 175 143 } 176 144 //****************************************************************************** … … 179 147 { 180 148 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 //****************************************************************************** 190 BOOL 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); 149 return CURSORICON_Copy( 0, hIcon ); 150 } 151 /********************************************************************** 152 * GetIconInfo (USER32.242) 153 */ 154 BOOL WINAPI GetIconInfo(HICON hIcon, ICONINFO *iconinfo) 155 { 156 CURSORICONINFO *ciconinfo; 157 158 dprintf(("GetIconInfo %x %x", hIcon, iconinfo)); 159 160 ciconinfo = (CURSORICONINFO *)GlobalLock((HGLOBAL)hIcon); 161 if (!ciconinfo) 162 return FALSE; 163 164 if((ciconinfo->ptHotSpot.x == ICON_HOTSPOT) && 165 (ciconinfo->ptHotSpot.y == ICON_HOTSPOT)) 166 { 167 iconinfo->fIcon = TRUE; 168 iconinfo->xHotspot = ciconinfo->nWidth / 2; 169 iconinfo->yHotspot = ciconinfo->nHeight / 2; 170 } 171 else 172 { 173 iconinfo->fIcon = FALSE; 174 iconinfo->xHotspot = ciconinfo->ptHotSpot.x; 175 iconinfo->yHotspot = ciconinfo->ptHotSpot.y; 176 } 177 178 //Create new bitmaps for the color and mask data; application is responsible 179 //for deleteing them (according to docs & verified in NT4) 180 if(ciconinfo->bBitsPerPixel > 1) 181 { 182 BITMAPINFO* pInfo; 183 int colorsize = 0; 184 int coloroff; 185 186 HDC hdc = CreateCompatibleDC(0); 187 188 if(ciconinfo->bBitsPerPixel <= 8) { 189 colorsize = (1<<ciconinfo->bBitsPerPixel)*sizeof(RGBQUAD); 190 } 191 else { 192 colorsize = 3*sizeof(DWORD); //color masks 193 } 194 pInfo = (BITMAPINFO *)malloc(ciconinfo->nHeight * ciconinfo->nWidthBytes + colorsize + sizeof(BITMAPINFO)); 195 memset(pInfo, 0, sizeof(BITMAPINFO)+colorsize); 196 197 pInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 198 pInfo->bmiHeader.biWidth = ciconinfo->nWidth; 199 pInfo->bmiHeader.biHeight = ciconinfo->nHeight, 200 pInfo->bmiHeader.biPlanes = ciconinfo->bPlanes; 201 pInfo->bmiHeader.biBitCount = ciconinfo->bBitsPerPixel; 202 pInfo->bmiHeader.biSizeImage= ciconinfo->nHeight * ciconinfo->nWidthBytes; 203 204 //offset in cursorinfo memory 205 coloroff = ciconinfo->nHeight * BITMAP_GetWidthBytes (ciconinfo->nWidth, 1); 206 207 char *src = (char *)(ciconinfo + 1) + coloroff; 208 if(ciconinfo->bBitsPerPixel <= 8) { 209 src += colorsize; //no color masks in cursorinfo data for bpp > 8 210 } 211 if(ciconinfo->bBitsPerPixel <= 8) { 212 memcpy(&pInfo->bmiColors[0], (char *)(ciconinfo + 1) + coloroff, colorsize); 213 } 214 //else TODO: color masks (curerntly unused in CreateDIBitmap) 215 216 iconinfo->hbmColor = CreateDIBitmap(hdc, &pInfo->bmiHeader, CBM_INIT, src, pInfo, DIB_RGB_COLORS); 217 218 free(pInfo); 219 DeleteDC(hdc); 220 } 221 else { 222 iconinfo->hbmColor = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight, 223 ciconinfo->bPlanes, ciconinfo->bBitsPerPixel, 224 (char *)(ciconinfo + 1) 225 + ciconinfo->nHeight * 226 BITMAP_GetWidthBytes (ciconinfo->nWidth, 1) ); 227 } 228 229 iconinfo->hbmMask = CreateBitmap ( ciconinfo->nWidth, ciconinfo->nHeight, 230 1, 1, (char *)(ciconinfo + 1)); 231 232 GlobalUnlock(hIcon); 233 234 return TRUE; 235 } 236 /*********************************************************************** 237 * CreateCursorIconIndirect (USER.408) 238 */ 239 HGLOBAL WIN32API CreateCursorIconIndirect( HINSTANCE hInstance, 240 CURSORICONINFO *info, 241 LPCVOID lpANDbits, 242 LPCVOID lpXORbits ) 243 { 244 HGLOBAL handle; 245 char *ptr; 246 int sizeAnd, sizeXor; 247 248 if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0; 249 info->nWidthBytes = BITMAP_GetWidthBytes(info->nWidth,info->bBitsPerPixel); 250 sizeXor = info->nHeight * info->nWidthBytes; 251 sizeAnd = info->nHeight * BITMAP_GetWidthBytes( info->nWidth, 1 ); 252 if (!(handle = GlobalAlloc( GMEM_MOVEABLE, 253 sizeof(CURSORICONINFO) + sizeXor + sizeAnd))) 254 return 0; 255 ptr = (char *)GlobalLock( handle ); 256 memcpy( ptr, info, sizeof(*info) ); 257 memcpy( ptr + sizeof(CURSORICONINFO), lpANDbits, sizeAnd ); 258 memcpy( ptr + sizeof(CURSORICONINFO) + sizeAnd, lpXORbits, sizeXor ); 259 GlobalUnlock( handle ); 260 return handle; 261 } 262 /********************************************************************** 263 * CURSORICON_Load 264 * 265 * Load a cursor or icon from resource or file. 266 */ 267 HGLOBAL CURSORICON_Load( HINSTANCE hInstance, LPCWSTR name, 268 INT width, INT height, INT colors, 269 BOOL fCursor, UINT loadflags ) 270 { 271 HANDLE handle = 0, h = 0; 272 HANDLE hRsrc; 273 CURSORICONDIR *dir; 274 CURSORICONDIRENTRY *dirEntry; 275 LPBYTE bits; 276 277 if ( loadflags & LR_LOADFROMFILE ) /* Load from file */ 278 { 279 LPBYTE *ptr; 280 if (!CURSORICON_SimulateLoadingFromResourceW((LPWSTR)name, fCursor, &dir, &ptr)) 281 return 0; 282 if (fCursor) 283 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(dir, width, height, 1); 284 else 285 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(dir, width, height, colors); 286 bits = ptr[dirEntry->wResId-1]; 287 h = CURSORICON_CreateFromResource( 0, 0, bits, dirEntry->dwBytesInRes, 288 !fCursor, 0x00030000, width, height, loadflags); 289 HeapFree( GetProcessHeap(), 0, dir ); 290 HeapFree( GetProcessHeap(), 0, ptr ); 291 } 292 else /* Load from resource */ 293 { 294 HANDLE hGroupRsrc; 295 WORD wResId; 296 DWORD dwBytesInRes; 297 BOOL bIsGroup = TRUE; 298 299 /* Get directory resource ID */ 300 if (!hInstance) 301 { 302 hRsrc = FindResourceW(hInstanceUser32, name, fCursor ? RT_CURSORW : RT_ICONW); 303 if(!hRsrc) { 304 hRsrc = FindResourceW(hInstanceUser32, name, fCursor ? RT_GROUP_CURSORW : RT_GROUP_ICONW); 305 } 306 else bIsGroup = FALSE; 307 308 if(!hRsrc) return 0; 309 310 hInstance = hInstanceUser32; 311 } 312 else { 313 hRsrc = FindResourceW(hInstance, name, fCursor ? RT_GROUP_CURSORW : RT_GROUP_ICONW); 314 if(!hRsrc) return 0; 315 } 316 hGroupRsrc = hRsrc; 317 318 if(bIsGroup) { 319 /* Find the best entry in the directory */ 320 321 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0; 322 if (!(dir = (CURSORICONDIR*)LockResource( handle ))) return 0; 323 324 if (fCursor) 325 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir, 326 width, height, 1); 327 else 328 dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir, 329 width, height, colors ); 330 if (!dirEntry) return 0; 331 wResId = dirEntry->wResId; 332 dwBytesInRes = dirEntry->dwBytesInRes; 333 FreeResource( handle ); 334 335 /* Load the resource */ 336 if (!(hRsrc = FindResourceW(hInstance,MAKEINTRESOURCEW(wResId), 337 fCursor ? RT_CURSORW : RT_ICONW ))) return 0; 338 } 339 340 if (!(handle = LoadResource( hInstance, hRsrc ))) return 0; 341 bits = (LPBYTE)LockResource( handle ); 342 h = CURSORICON_CreateFromResource( 0, 0, bits, dwBytesInRes, 343 !fCursor, 0x00030000, width, height, loadflags); 344 FreeResource( handle ); 345 346 } 347 348 return h; 349 } 350 351 /********************************************************************* 352 * The main purpose of this function is to create fake resource directory 353 * and fake resource entries. There are several reasons for this: 354 * - CURSORICONDIR and CURSORICONFILEDIR differ in sizes and their 355 * fields 356 * There are some "bad" cursor files which do not have 357 * bColorCount initialized but instead one must read this info 358 * directly from corresponding DIB sections 359 * Note: wResId is index to array of pointer returned in ptrs (origin is 1) 360 */ 361 BOOL CURSORICON_SimulateLoadingFromResourceW( LPWSTR filename, BOOL fCursor, 362 CURSORICONDIR **res, LPBYTE **ptr) 363 { 364 LPBYTE _free; 365 CURSORICONFILEDIR *bits; 366 int entries, size, i; 367 HANDLE hMapping = 0; 368 369 *res = NULL; 370 *ptr = NULL; 371 372 hMapping = VIRTUAL_MapFileW( filename, (LPVOID *)&bits, TRUE); 373 if(hMapping == INVALID_HANDLE_VALUE) 374 return FALSE; 375 376 /* FIXME: test for inimated icons 377 * hack to load the first icon from the *.ani file 378 */ 379 if ( *(LPDWORD)bits==0x46464952 ) /* "RIFF" */ 380 { 381 LPBYTE pos = (LPBYTE) bits; 382 dprintf(("Animated icons not correctly implemented! %p \n", bits)); 383 384 for (;;) 385 { 386 if (*(LPDWORD)pos==0x6e6f6369) /* "icon" */ 387 { 388 dprintf(("icon entry found! %p\n", bits)); 389 pos+=4; 390 if ( !*(LPWORD) pos==0x2fe) /* iconsize */ 391 { 392 goto fail; 393 } 394 bits=(CURSORICONFILEDIR*)(pos+4); 395 dprintf(("icon size ok. offset=%p \n", bits)); 396 break; 397 } 398 pos+=2; 399 if (pos>=(LPBYTE)bits+766) goto fail; 400 } 401 } 402 if (!(entries = bits->idCount)) goto fail; 403 size = sizeof(CURSORICONDIR) + sizeof(CURSORICONDIRENTRY) * (entries - 1); 404 _free = (LPBYTE) size; 405 406 for (i=0; i < entries; i++) 407 size += bits->idEntries[i].dwDIBSize + (fCursor ? sizeof(POINT16): 0); 408 409 if (!(*ptr = (LPBYTE *)HeapAlloc( GetProcessHeap(), 0, 410 entries * sizeof (CURSORICONDIRENTRY*)))) goto fail; 411 if (!(*res = (CURSORICONDIR *)HeapAlloc( GetProcessHeap(), 0, size))) goto fail; 412 413 _free = (LPBYTE)(*res) + (int)_free; 414 memcpy((*res), bits, 6); 415 for (i=0; i<entries; i++) 416 { 417 ((LPBYTE*)(*ptr))[i] = _free; 418 if (fCursor) { 419 (*res)->idEntries[i].ResInfo.cursor.wWidth=bits->idEntries[i].bWidth; 420 (*res)->idEntries[i].ResInfo.cursor.wHeight=bits->idEntries[i].bHeight; 421 ((LPPOINT16)_free)->x=bits->idEntries[i].xHotspot; 422 ((LPPOINT16)_free)->y=bits->idEntries[i].yHotspot; 423 _free+=sizeof(POINT16); 424 } 425 else { 426 (*res)->idEntries[i].ResInfo.icon.bWidth=bits->idEntries[i].bWidth; 427 (*res)->idEntries[i].ResInfo.icon.bHeight=bits->idEntries[i].bHeight; 428 (*res)->idEntries[i].ResInfo.icon.bColorCount = bits->idEntries[i].bColorCount; 429 } 430 (*res)->idEntries[i].wPlanes=1; 431 (*res)->idEntries[i].wBitCount = ((LPBITMAPINFOHEADER)((LPBYTE)bits + 432 bits->idEntries[i].dwDIBOffset))->biBitCount; 433 (*res)->idEntries[i].dwBytesInRes = bits->idEntries[i].dwDIBSize; 434 (*res)->idEntries[i].wResId=i+1; 435 436 memcpy(_free,(LPBYTE)bits +bits->idEntries[i].dwDIBOffset, 437 (*res)->idEntries[i].dwBytesInRes); 438 _free += (*res)->idEntries[i].dwBytesInRes; 439 } 440 UnmapViewOfFile( bits ); 441 CloseHandle(hMapping); 442 return TRUE; 443 444 fail: 445 if (*res) HeapFree( GetProcessHeap(), 0, *res ); 446 if (*ptr) HeapFree( GetProcessHeap(), 0, *ptr ); 447 448 UnmapViewOfFile( bits ); 449 CloseHandle(hMapping); 450 return FALSE; 451 } 452 453 /********************************************************************** 454 * CURSORICON_CreateFromResource 455 * 456 * Create a cursor or icon from in-memory resource template. 457 * 458 * FIXME: Convert to mono when cFlag is LR_MONOCHROME. Do something 459 * with cbSize parameter as well. 460 */ 461 static HGLOBAL CURSORICON_CreateFromResource( HINSTANCE hInstance, HGLOBAL hObj, LPBYTE bits, 462 UINT cbSize, BOOL bIcon, DWORD dwVersion, 463 INT width, INT height, UINT loadflags ) 464 { 465 int sizeAnd, sizeXor; 466 HBITMAP hAndBits = 0, hXorBits = 0; /* error condition for later */ 467 BITMAP bmpXor, bmpAnd; 468 POINT16 hotspot; 469 BITMAPINFO *bmi; 470 HDC hdc = 0; 471 BOOL DoStretch; 472 INT size, colortablesize; 473 474 hotspot.x = ICON_HOTSPOT; 475 hotspot.y = ICON_HOTSPOT; 476 477 if (dwVersion == 0x00020000) 478 { 479 dprintf(("CURSORICON_CreateFromResource 2.xx resources are not supported")); 480 return 0; 481 } 482 483 if (bIcon) { 484 bmi = (BITMAPINFO *)bits; 485 } 486 else /* get the hotspot */ 487 { 488 POINT16 *pt = (POINT16 *)bits; 489 hotspot = *pt; 490 bmi = (BITMAPINFO *)(pt + 1); 491 } 492 size = DIB_BitmapInfoSize(bmi, DIB_RGB_COLORS); 493 494 if (!width) width = bmi->bmiHeader.biWidth; 495 if (!height) height = bmi->bmiHeader.biHeight/2; 496 497 DoStretch = (bmi->bmiHeader.biHeight/2 != height) || (bmi->bmiHeader.biWidth != width); 498 499 /* Check bitmap header */ 500 if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) && 501 (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) || 502 bmi->bmiHeader.biCompression != BI_RGB) ) 503 { 504 return 0; 505 } 506 507 if( (hdc = GetDC( 0 )) ) 508 { 509 BITMAPINFO* pInfo; 510 511 /* Make sure we have room for the monochrome bitmap later on. 512 * Note that BITMAPINFOINFO and BITMAPCOREHEADER are the same 513 * up to and including the biBitCount. In-memory icon resource 514 * format is as follows: 515 * 516 * BITMAPINFOHEADER icHeader // DIB header 517 * RGBQUAD icColors[] // Color table 518 * BYTE icXOR[] // DIB bits for XOR mask 519 * BYTE icAND[] // DIB bits for AND mask 520 */ 521 522 if ((pInfo = (BITMAPINFO *)HeapAlloc( GetProcessHeap(), 0, 523 max(size, sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD))))) 524 { 525 memcpy( pInfo, bmi, size ); 526 pInfo->bmiHeader.biHeight /= 2; 527 528 /* Create the XOR bitmap */ 529 if (DoStretch) 530 { 531 if(bIcon) 532 { 533 hXorBits = CreateCompatibleBitmap(hdc, width, height); 534 } 535 else 536 { 537 hXorBits = CreateBitmap(width, height, 1, 1, NULL); 538 } 539 if(hXorBits) 540 { 541 HBITMAP hOld; 542 HDC hMem = CreateCompatibleDC(hdc); 543 BOOL res; 544 545 if (hMem) { 546 hOld = SelectObject(hMem, hXorBits); 547 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0, 548 bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight/2, 549 (char*)bmi + size, pInfo, DIB_RGB_COLORS, SRCCOPY); 550 SelectObject(hMem, hOld); 551 DeleteDC(hMem); 552 } 553 else res = FALSE; 554 if (!res) { 555 DeleteObject(hXorBits); 556 hXorBits = 0; 557 } 558 } 559 } 560 else 561 { 562 hXorBits = CreateDIBitmap(hdc, &pInfo->bmiHeader, 563 CBM_INIT, (char*)bmi + size, pInfo, DIB_RGB_COLORS ); 564 } 565 if( hXorBits ) 566 { 567 char* xbits = (char *)bmi + size + DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth, 568 bmi->bmiHeader.biHeight, 569 bmi->bmiHeader.biBitCount) / 2; 570 571 pInfo->bmiHeader.biBitCount = 1; 572 if (pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER)) 573 { 574 RGBQUAD *rgb = pInfo->bmiColors; 575 576 pInfo->bmiHeader.biClrUsed = pInfo->bmiHeader.biClrImportant = 2; 577 rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00; 578 rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff; 579 rgb[0].rgbReserved = rgb[1].rgbReserved = 0; 580 } 581 else 582 { 583 RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pInfo) + 1); 584 585 rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00; 586 rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff; 587 } 588 589 /* Create the AND bitmap */ 590 if (DoStretch) 591 { 592 if ((hAndBits = CreateBitmap(width, height, 1, 1, NULL))) 593 { 594 HBITMAP hOld; 595 HDC hMem = CreateCompatibleDC(hdc); 596 BOOL res; 597 598 if (hMem) { 599 hOld = SelectObject(hMem, hAndBits); 600 res = StretchDIBits(hMem, 0, 0, width, height, 0, 0, 601 pInfo->bmiHeader.biWidth, pInfo->bmiHeader.biHeight, 602 xbits, pInfo, DIB_RGB_COLORS, SRCCOPY); 603 SelectObject(hMem, hOld); 604 DeleteDC(hMem); 605 } 606 else res = FALSE; 607 if (!res) { 608 DeleteObject(hAndBits); hAndBits = 0; 609 } 610 } 611 } 612 else { 613 //SvL: Must use CreateBitmap here as CreateDIBitmap converts data to 8bpp (GetObjectA info -> 8 bpp) 198 614 #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 } 615 int linewidth = BITMAP_GetWidthBytes(width, 1); 616 617 char *newpix = (char *)malloc(linewidth*height); 618 619 newpix += ((height-1)*linewidth); 620 621 for(int i=0;i<height;i++) { 622 memcpy(newpix, xbits, linewidth); 623 newpix -= linewidth; 624 xbits += linewidth; 625 } 626 newpix += linewidth; 627 hAndBits = CreateBitmap(width, height, 1, 1, newpix); 628 629 free(newpix); 630 631 #else 632 hAndBits = CreateDIBitmap(hdc, &pInfo->bmiHeader, 633 CBM_INIT, xbits, pInfo, DIB_RGB_COLORS ); 220 634 #endif 221 return rc; 222 } 635 } 636 if( !hAndBits ) 637 DeleteObject( hXorBits ); 638 } 639 HeapFree( GetProcessHeap(), 0, pInfo ); 640 } 641 ReleaseDC( 0, hdc ); 642 } 643 644 if( !hXorBits || !hAndBits ) 645 { 646 dprintf(("\tunable to create an icon bitmap.\n")); 647 return 0; 648 } 649 650 /* Now create the CURSORICONINFO structure */ 651 GetObjectA( hXorBits, sizeof(bmpXor), &bmpXor ); 652 GetObjectA( hAndBits, sizeof(bmpAnd), &bmpAnd ); 653 colortablesize = 0; 654 655 if(bmpXor.bmBitsPixel <= 8) { 656 colortablesize = sizeof(RGBQUAD)*(1<<bmpXor.bmBitsPixel); 657 sizeXor = bmpXor.bmHeight * bmpXor.bmWidthBytes + colortablesize; 658 } 659 else sizeXor = bmpXor.bmHeight * bmpXor.bmWidthBytes; 660 661 sizeAnd = bmpAnd.bmHeight * bmpAnd.bmWidthBytes; 662 663 if (hObj) hObj = GlobalReAlloc( hObj, 664 sizeof(CURSORICONINFO) + sizeXor + sizeAnd, GMEM_MOVEABLE ); 665 if (!hObj) hObj = GlobalAlloc( GMEM_MOVEABLE, 666 sizeof(CURSORICONINFO) + sizeXor + sizeAnd ); 667 if (hObj) 668 { 669 CURSORICONINFO *info; 670 671 info = (CURSORICONINFO *)GlobalLock( hObj ); 672 info->ptHotSpot.x = hotspot.x; 673 info->ptHotSpot.y = hotspot.y; 674 info->nWidth = bmpXor.bmWidth; 675 info->nHeight = bmpXor.bmHeight; 676 info->nWidthBytes = bmpXor.bmWidthBytes; 677 info->bPlanes = bmpXor.bmPlanes; 678 info->bBitsPerPixel = bmpXor.bmBitsPixel; 679 info->hColorBmp = hXorBits; 680 681 /* Transfer the bitmap bits to the CURSORICONINFO structure */ 682 GetBitmapBits( hAndBits, sizeAnd, (char *)(info + 1)); 683 684 if(bmpXor.bmBitsPixel > 1) 685 { 686 BITMAPINFO* pInfo = (BITMAPINFO *)malloc(sizeof(BITMAPINFO)+colortablesize+3*sizeof(DWORD)); //+ extra space for > 8bpp images 687 HBITMAP oldbmp; 688 689 hdc = CreateCompatibleDC(0); 690 691 pInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 692 pInfo->bmiHeader.biPlanes = info->bPlanes; 693 pInfo->bmiHeader.biBitCount = info->bBitsPerPixel; 694 695 GetDIBits(hdc, hXorBits, 0, bmpXor.bmHeight, (char *)(info + 1) + sizeAnd + colortablesize, pInfo, DIB_RGB_COLORS); 696 if(colortablesize) { 697 memcpy((char *)(info + 1) + sizeAnd, (char *)&pInfo->bmiHeader + pInfo->bmiHeader.biSize, colortablesize); 698 } 699 700 DeleteDC(hdc); 701 free(pInfo); 702 } 703 else { 704 GetBitmapBits( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd); 705 } 706 GlobalUnlock( hObj ); 707 } 708 709 DeleteObject( hAndBits ); 710 DeleteObject( hXorBits ); 711 return hObj; 712 } 713 714 /********************************************************************** 715 * CURSORICON_Destroy (USER.610) 716 * 717 * This routine is actually exported from Win95 USER under the name 718 * DestroyIcon32 ... The behaviour implemented here should mimic 719 * the Win95 one exactly, especially the return values, which 720 * depend on the setting of various flags. 721 */ 722 WORD WIN32API CURSORICON_Destroy( HGLOBAL handle, UINT flags ) 723 { 724 WORD retv; 725 726 #if 0 727 /* Check whether destroying active cursor */ 728 729 if ( hActiveCursor == handle ) 730 { 731 ERR_(cursor)("Destroying active cursor!\n" ); 732 SetCursor( 0 ); 733 } 734 /* Try shared cursor/icon first */ 735 736 if ( !(flags & CID_NONSHARED) ) 737 { 738 INT count = CURSORICON_DelSharedIcon( handle ); 739 740 if ( count != -1 ) 741 return (flags & CID_WIN32)? TRUE : (count == 0); 742 743 /* FIXME: OEM cursors/icons should be recognized */ 744 } 745 #endif 746 /* Now assume non-shared cursor/icon */ 747 748 retv = GlobalFree( handle ); 749 return (flags & CID_RESOURCE)? retv : TRUE; 750 } 751 752 /*********************************************************************** 753 * CURSORICON_Copy 754 * 755 * Make a copy of a cursor or icon. 756 */ 757 static HGLOBAL CURSORICON_Copy( HINSTANCE hInstance, HGLOBAL handle ) 758 { 759 char *ptrOld, *ptrNew; 760 int size; 761 HGLOBAL hNew; 762 763 if (!(ptrOld = (char *)GlobalLock( handle ))) return 0; 764 765 size = GlobalSize( handle ); 766 hNew = GlobalAlloc( GMEM_MOVEABLE, size ); 767 ptrNew = (char *)GlobalLock( hNew ); 768 memcpy( ptrNew, ptrOld, size ); 769 GlobalUnlock( handle ); 770 GlobalUnlock( hNew ); 771 return hNew; 772 } 773 774 /************************************************************************* 775 * CURSORICON_ExtCopy 776 * 777 * Copies an Image from the Cache if LR_COPYFROMRESOURCE is specified 778 * 779 * PARAMS 780 * Handle [I] handle to an Image 781 * nType [I] Type of Handle (IMAGE_CURSOR | IMAGE_ICON) 782 * iDesiredCX [I] The Desired width of the Image 783 * iDesiredCY [I] The desired height of the Image 784 * nFlags [I] The flags from CopyImage 785 * 786 * RETURNS 787 * Success: The new handle of the Image 788 * 789 * NOTES 790 * LR_COPYDELETEORG and LR_MONOCHROME are currently not implemented. 791 * LR_MONOCHROME should be implemented by CURSORICON_CreateFromResource. 792 * LR_COPYFROMRESOURCE will only work if the Image is in the Cache. 793 * 794 * 795 */ 796 797 HGLOBAL CURSORICON_ExtCopy(HGLOBAL Handle, UINT nType, 798 INT iDesiredCX, INT iDesiredCY, 799 UINT nFlags) 800 { 801 HGLOBAL hNew=0; 802 803 if(Handle == 0) 804 { 805 return 0; 806 } 807 808 hNew = CURSORICON_Copy(0, Handle); 809 return hNew; 810 } 811 223 812 /********************************************************************** 224 813 * CURSORICON_FindBestIcon … … 329 918 } 330 919 /********************************************************************** 331 * LookupIconIdFromDirectoryEx 16(USER.364)920 * LookupIconIdFromDirectoryEx (USER.364) 332 921 * 333 922 * FIXME: exact parameter sizes … … 373 962 bIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), bIcon ? 0 : LR_MONOCHROME ); 374 963 } 375 /*************************************************************************376 * CURSORICON_ExtCopy377 *378 * Copies an Image from the Cache if LR_COPYFROMRESOURCE is specified379 *380 * PARAMS381 * Handle [I] handle to an Image382 * nType [I] Type of Handle (IMAGE_CURSOR | IMAGE_ICON)383 * iDesiredCX [I] The Desired width of the Image384 * iDesiredCY [I] The desired height of the Image385 * nFlags [I] The flags from CopyImage386 *387 * RETURNS388 * Success: The new handle of the Image389 *390 * NOTES391 * 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 instead397 *398 */399 HGLOBAL 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_COPYFROMRESOURCE413 && (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 needed425 */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 dimension436 */437 ICONINFO iconinfo;438 439 GetIconInfo(Handle, &iconinfo);440 hNew = CreateIconIndirect(&iconinfo, bIsIcon, iDesiredCX, iDesiredCY, nFlags);441 }442 else443 {444 if(bIsIcon) {445 return CopyIcon(Handle);446 }447 else return CopyCursor(Handle);448 }449 return hNew;450 }451 964 //****************************************************************************** 452 965 //******************************************************************************
Note:
See TracChangeset
for help on using the changeset viewer.