diff --git a/reactos/include/win32k/cursoricon.h b/reactos/include/win32k/cursoricon.h index e7f0fde9e78..a5a233bd922 100644 --- a/reactos/include/win32k/cursoricon.h +++ b/reactos/include/win32k/cursoricon.h @@ -15,27 +15,50 @@ typedef struct _ICONIMAGE BYTE icAND[1]; // DIB bits for AND mask } ICONIMAGE, *LPICONIMAGE __attribute__((packed)); +typedef struct _CURSORIMAGE +{ + BITMAPINFOHEADER icHeader; // DIB header + RGBQUAD icColors[1]; // Color table + BYTE icXOR[1]; // DIB bits for XOR mask + BYTE icAND[1]; // DIB bits for AND mask +} CURSORIMAGE, *LPCURSORIMAGE __attribute__((packed)); + +typedef struct +{ + BYTE bWidth; + BYTE bHeight; + BYTE bColorCount; + BYTE bReserved; +} ICONRESDIR __attribute__((packed)); + +typedef struct +{ + WORD wWidth; + WORD wHeight; +} CURSORRESDIR __attribute__((packed)); + +typedef struct +{ + WORD wPlanes; // Number of Color Planes in the XOR image + WORD wBitCount; // Bits per pixel in the XOR image +} ICONDIR __attribute__((packed)); + +typedef struct +{ + WORD wXHotspot; // Number of Color Planes in the XOR image + WORD wYHotspot; // Bits per pixel in the XOR image +} CURSORDIR __attribute__((packed)); + typedef struct { BYTE bWidth; // Width, in pixels, of the icon image BYTE bHeight; // Height, in pixels, of the icon image BYTE bColorCount; // Number of colors in image (0 if >=8bpp) BYTE bReserved; // Reserved ( must be 0) -} ICONDIR __attribute__((packed)); - -typedef struct -{ - WORD wWidth; //Width, in pixels of the cursor image - WORD wHeight; //Hight, in pixles of the cursor image -} CURSORDIR __attribute__((packed)); - -typedef struct -{ union + union { ICONDIR icon; CURSORDIR cursor; } Info; - WORD wPlanes; // Number of Color Planes in the XOR image - WORD wBitCount; // Bits per pixel in the XOR image DWORD dwBytesInRes; // How many bytes in this resource? DWORD dwImageOffset; // Where in the file is this image? } CURSORICONDIRENTRY __attribute__((packed)); @@ -49,23 +72,24 @@ typedef struct } CURSORICONDIR __attribute__((packed)); typedef struct -{ union - { ICONDIR icon; - CURSORDIR cursor; - } Info; - WORD wPlanes; // Color Planes - WORD wBitCount; // Bits per pixel - DWORD dwBytesInRes; // how many bytes in this resource? - WORD nID; // the ID -} GRPICONDIRENTRY __attribute__((packed)); +{ + union + { ICONRESDIR icon; + CURSORRESDIR cursor; + } ResInfo; + WORD wPlanes; // Color Planes + WORD wBitCount; // Bits per pixel + DWORD dwBytesInRes; // how many bytes in this resource? + WORD nID; // the ID +} GRPCURSORICONDIRENTRY __attribute__((packed)); typedef struct { WORD idReserved; // Reserved (must be 0) WORD idType; // Resource type (1 for icons) WORD idCount; // How many images? - GRPICONDIRENTRY idEntries[1] __attribute__((packed)); // The entries for each image -} GRPICONDIR __attribute__((packed)); + GRPCURSORICONDIRENTRY idEntries[1] __attribute__((packed)); // The entries for each image +} GRPCURSORICONDIR __attribute__((packed)); /* GDI logical Icon/Cursor object */ typedef struct _ICONCURSOROBJ diff --git a/reactos/lib/user32/user32.def b/reactos/lib/user32/user32.def index 239a3cb4455..3ec7d4a50fa 100644 --- a/reactos/lib/user32/user32.def +++ b/reactos/lib/user32/user32.def @@ -441,8 +441,7 @@ LockWindowUpdate@4 LockWorkStation@0 LookupIconIdFromDirectory@8 LookupIconIdFromDirectoryEx@20 -;MBToWCSEx -;MB_GetString +MBToWCSEx@24 MapDialogRect@8 MapVirtualKeyA@8 MapVirtualKeyExA@12 @@ -680,7 +679,7 @@ VkKeyScanA@4 VkKeyScanExA@8 VkKeyScanExW@8 VkKeyScanW@4 -;WCSToMBEx +WCSToMBEx@24 ;WINNLSEnableIME ;WINNLSGetEnableStatus ;WINNLSGetIMEHotkey diff --git a/reactos/lib/user32/user32.edf b/reactos/lib/user32/user32.edf index 49c531e309c..7f3a33a42b7 100644 --- a/reactos/lib/user32/user32.edf +++ b/reactos/lib/user32/user32.edf @@ -442,8 +442,7 @@ LockWindowUpdate=LockWindowUpdate@4 LockWorkStation=LockWorkStation@0 LookupIconIdFromDirectory=LookupIconIdFromDirectory@8 LookupIconIdFromDirectoryEx=LookupIconIdFromDirectoryEx@20 -;MBToWCSEx -;MB_GetString +MBToWCSEx=MBToWCSEx@24 MapDialogRect=MapDialogRect@8 MapVirtualKeyA=MapVirtualKeyA@8 MapVirtualKeyExA=MapVirtualKeyExA@12 @@ -684,7 +683,7 @@ VkKeyScanA=VkKeyScanA@4 VkKeyScanExA=VkKeyScanExA@8 VkKeyScanExW=VkKeyScanExW@8 VkKeyScanW=VkKeyScanW@4 -;WCSToMBEx +WCSToMBEx=WCSToMBEx@24 ;WINNLSEnableIME ;WINNLSGetEnableStatus ;WINNLSGetIMEHotkey diff --git a/reactos/lib/user32/windows/bitmap.c b/reactos/lib/user32/windows/bitmap.c index 42e45a57814..e02379e45fc 100644 --- a/reactos/lib/user32/windows/bitmap.c +++ b/reactos/lib/user32/windows/bitmap.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: bitmap.c,v 1.12 2003/08/07 04:03:24 royce Exp $ +/* $Id: bitmap.c,v 1.13 2003/08/20 14:08:18 weiden Exp $ * * PROJECT: ReactOS user32.dll * FILE: lib/user32/windows/input.c @@ -35,8 +35,9 @@ #include /*forward declerations... actualy in user32\windows\icon.c but usful here****/ -HICON ICON_CreateIconFromData(HDC hDC, PVOID ImageData, ICONIMAGE* IconImage, int cxDesired, int cyDesired); +HICON ICON_CreateIconFromData(HDC hDC, PVOID ImageData, ICONIMAGE* IconImage, int cxDesired, int cyDesired, int xHotspot, int yHotspot); CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width, int height, int colors); +CURSORICONDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir, int width, int height, int colors); /* FUNCTIONS *****************************************************************/ @@ -76,8 +77,166 @@ LoadImageA(HINSTANCE hinst, HANDLE STATIC LoadCursorImage(HINSTANCE hinst, LPCWSTR lpszName, UINT fuLoad) { - DbgPrint("FIXME: Need support for loading cursor images.\n"); - return(NULL); + HANDLE hResource; + HANDLE h2Resource; + HANDLE hFile; + HANDLE hSection; + CURSORICONDIR* IconDIR; + HDC hScreenDc; + HANDLE hIcon; + ULONG HeaderSize; + ULONG ColourCount; + PVOID Data; + CURSORICONDIRENTRY* dirEntry; + ICONIMAGE* SafeIconImage; + GRPCURSORICONDIR* IconResDir; + INT id; + ICONIMAGE *ResIcon; + + if (fuLoad & LR_SHARED) + DbgPrint("FIXME: need LR_SHARED support Loading cursor images\n"); + + if (!(fuLoad & LR_LOADFROMFILE)) + { + if (hinst == NULL) + { + hinst = GetModuleHandleW(L"USER32"); + } + hResource = FindResourceW(hinst, lpszName, RT_GROUP_CURSOR); + if (hResource == NULL) + { + return(NULL); + } + + hResource = LoadResource(hinst, hResource); + if (hResource == NULL) + { + return(NULL); + } + IconResDir = LockResource(hResource); + if (IconResDir == NULL) + { + return(NULL); + } + + //find the best fitting in the IconResDir for this resolution + id = LookupIconIdFromDirectoryEx((PBYTE) IconResDir, TRUE, + 32, 32, fuLoad & (LR_DEFAULTCOLOR | LR_MONOCHROME)); + + h2Resource = FindResourceW(hinst, + MAKEINTRESOURCEW(id), + MAKEINTRESOURCEW(RT_ICON)); + + hResource = LoadResource(hinst, h2Resource); + if (hResource == NULL) + { + return(NULL); + } + + ResIcon = LockResource(hResource); + if (ResIcon == NULL) + { + return(NULL); + } + return CreateIconFromResourceEx((PBYTE) ResIcon, + SizeofResource(hinst, h2Resource), FALSE, 0x00030000, + 32, 32, fuLoad & (LR_DEFAULTCOLOR | LR_MONOCHROME)); + } + else + { + hFile = CreateFileW(lpszName, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + 0, + NULL); + if (hFile == NULL) + { + return(NULL); + } + + hSection = CreateFileMappingW(hFile, + NULL, + PAGE_READONLY, + 0, + 0, + NULL); + + CloseHandle(hFile); + if (hSection == NULL) + { + return(NULL); + } + IconDIR = MapViewOfFile(hSection, + FILE_MAP_READ, + 0, + 0, + 0); + + CloseHandle(hSection); + if (IconDIR == NULL) + { + return(NULL); + } + + //pick the best size. + dirEntry = (CURSORICONDIRENTRY *) CURSORICON_FindBestIcon( IconDIR, 32, 32, 1); + + + if (!dirEntry) + { + if (fuLoad & LR_LOADFROMFILE) + { + UnmapViewOfFile(IconDIR); + } + return(NULL); + } + + SafeIconImage = RtlAllocateHeap(RtlGetProcessHeap(), 0, dirEntry->dwBytesInRes); + + memcpy(SafeIconImage, ((PBYTE)IconDIR) + dirEntry->dwImageOffset, dirEntry->dwBytesInRes); + } + + //at this point we have a copy of the icon image to play with + + SafeIconImage->icHeader.biHeight = SafeIconImage->icHeader.biHeight /2; + + if (SafeIconImage->icHeader.biSize == sizeof(BITMAPCOREHEADER)) + { + BITMAPCOREHEADER* Core = (BITMAPCOREHEADER*)SafeIconImage; + ColourCount = (Core->bcBitCount <= 8) ? (1 << Core->bcBitCount) : 0; + HeaderSize = sizeof(BITMAPCOREHEADER) + ColourCount * sizeof(RGBTRIPLE); + } + else + { + ColourCount = SafeIconImage->icHeader.biClrUsed; + if (ColourCount == 0 && SafeIconImage->icHeader.biBitCount <= 8) + { + ColourCount = 1 << SafeIconImage->icHeader.biBitCount; + } + HeaderSize = sizeof(BITMAPINFOHEADER) + ColourCount * sizeof(RGBQUAD); + } + + //make data point to the start of the XOR image data + Data = (PBYTE)SafeIconImage + HeaderSize; + + + //get a handle to the screen dc, the icon we create is going to be compatable with this + hScreenDc = CreateDCW(L"DISPLAY", NULL, NULL, NULL); + if (hScreenDc == NULL) + { + if (fuLoad & LR_LOADFROMFILE) + { + RtlFreeHeap(RtlGetProcessHeap(), 0, SafeIconImage); + UnmapViewOfFile(IconDIR); + } + return(NULL); + } + + hIcon = ICON_CreateIconFromData(hScreenDc, Data, SafeIconImage, 32, 32, dirEntry->Info.cursor.wXHotspot, dirEntry->Info.cursor.wYHotspot); + RtlFreeHeap(RtlGetProcessHeap(), 0, SafeIconImage); + return hIcon; } @@ -96,7 +255,7 @@ LoadIconImage(HINSTANCE hinst, LPCWSTR lpszName, INT width, INT height, UINT fuL PVOID Data; CURSORICONDIRENTRY* dirEntry; ICONIMAGE* SafeIconImage; - GRPICONDIR* IconResDir; + GRPCURSORICONDIR* IconResDir; INT id; ICONIMAGE *ResIcon; @@ -241,7 +400,7 @@ LoadIconImage(HINSTANCE hinst, LPCWSTR lpszName, INT width, INT height, UINT fuL return(NULL); } - hIcon = ICON_CreateIconFromData(hScreenDc, Data, SafeIconImage, width, height); + hIcon = ICON_CreateIconFromData(hScreenDc, Data, SafeIconImage, width, height, width/2, height/2); RtlFreeHeap(RtlGetProcessHeap(), 0, SafeIconImage); return hIcon; } diff --git a/reactos/lib/user32/windows/icon.c b/reactos/lib/user32/windows/icon.c index f36b85e03db..bce2ac6d7bc 100644 --- a/reactos/lib/user32/windows/icon.c +++ b/reactos/lib/user32/windows/icon.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: icon.c,v 1.8 2003/08/19 11:48:49 weiden Exp $ +/* $Id: icon.c,v 1.9 2003/08/20 14:08:19 weiden Exp $ * * PROJECT: ReactOS user32.dll * FILE: lib/user32/windows/icon.c @@ -37,7 +37,7 @@ /* FUNCTIONS *****************************************************************/ HICON -ICON_CreateIconFromData(HDC hDC, PVOID ImageData, ICONIMAGE* IconImage, int cxDesired, int cyDesired) +ICON_CreateIconFromData(HDC hDC, PVOID ImageData, ICONIMAGE* IconImage, int cxDesired, int cyDesired, int xHotspot, int yHotspot) { HANDLE hXORBitmap; HANDLE hANDBitmap; @@ -87,8 +87,8 @@ ICON_CreateIconFromData(HDC hDC, PVOID ImageData, ICONIMAGE* IconImage, int cxDe RtlFreeHeap(RtlGetProcessHeap(), 0, bwBIH); IconInfo.fIcon = TRUE; - IconInfo.xHotspot = cxDesired/2; - IconInfo.yHotspot = cyDesired/2; + IconInfo.xHotspot = xHotspot; + IconInfo.yHotspot = yHotspot; IconInfo.hbmColor = hXORBitmap; IconInfo.hbmMask = hANDBitmap; @@ -179,8 +179,24 @@ CreateIconFromResourceEx( ULONG ColourCount; PVOID Data; HDC hScreenDc; + WORD wXHotspot; + WORD wYHotspot; - DPRINT("fIcon, dwVersion, cxDesired, cyDesired are all ignored in this implementation!\n"); + DPRINT("dwVersion, cxDesired, cyDesired are all ignored in this implementation!\n"); + + if (!fIcon) + { + wXHotspot = (WORD)*pbIconBits; + pbIconBits+=2; + wYHotspot = (WORD)*pbIconBits; + pbIconBits+=2; + cbIconBits-=4; + } + else + { + wXHotspot = cxDesired / 2; + wYHotspot = cyDesired / 2; + } //get an safe copy of the icon data SafeIconImage = RtlAllocateHeap(RtlGetProcessHeap(), 0, cbIconBits); @@ -213,7 +229,7 @@ CreateIconFromResourceEx( return(NULL); } - hIcon = ICON_CreateIconFromData(hScreenDc, Data, SafeIconImage, cxDesired, cyDesired); + hIcon = ICON_CreateIconFromData(hScreenDc, Data, SafeIconImage, cxDesired, cyDesired, wXHotspot, wYHotspot); RtlFreeHeap(RtlGetProcessHeap(), 0, SafeIconImage); return hIcon; } @@ -497,8 +513,8 @@ CURSORICON_FindBestCursor( CURSORICONDIR *dir, int width, int height, int colors iColorDiff = 0xFFFFFFFF; for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++) { - iTempXDiff = abs(width - entry->Info.icon.bWidth); - iTempYDiff = abs(height - entry->Info.icon.bHeight); + iTempXDiff = abs(width - entry->bWidth); + iTempYDiff = abs(height - entry->bHeight); if(iTotalDiff > (iTempXDiff + iTempYDiff)) { @@ -511,10 +527,10 @@ CURSORICON_FindBestCursor( CURSORICONDIR *dir, int width, int height, int colors /* Find Best Colors for Best Fit */ for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++) { - if(abs(width - entry->Info.icon.bWidth) == (int) iXDiff && - abs(height - entry->Info.icon.bHeight) == (int) iYDiff) + if(abs(width - entry->bWidth) == (int) iXDiff && + abs(height - entry->bHeight) == (int) iYDiff) { - iTempColorDiff = abs(colors - entry->Info.icon.bColorCount); + iTempColorDiff = abs(colors - entry->bColorCount); if(iColorDiff > iTempColorDiff) { @@ -549,9 +565,9 @@ CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width, int height, int colors) iColorDiff = 0xFFFFFFFF; for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++) { - iTempXDiff = abs(width - entry->Info.icon.bWidth); + iTempXDiff = abs(width - entry->bWidth); - iTempYDiff = abs(height - entry->Info.icon.bHeight); + iTempYDiff = abs(height - entry->bHeight); if(iTotalDiff > (iTempXDiff + iTempYDiff)) { @@ -564,10 +580,10 @@ CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width, int height, int colors) /* Find Best Colors for Best Fit */ for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++) { - if(abs(width - entry->Info.icon.bWidth) == (int) iXDiff && - abs(height - entry->Info.icon.bHeight) == (int) iYDiff) + if(abs(width - entry->bWidth) == (int) iXDiff && + abs(height - entry->bHeight) == (int) iYDiff) { - iTempColorDiff = abs(colors - entry->Info.icon.bColorCount); + iTempColorDiff = abs(colors - entry->bColorCount); if(iColorDiff > iTempColorDiff) { bestEntry = entry; @@ -592,12 +608,12 @@ LookupIconIdFromDirectoryEx( int cyDesired, UINT Flags) { - GRPICONDIR *dir = (GRPICONDIR*)presbits; + GRPCURSORICONDIR *dir = (GRPCURSORICONDIR*)presbits; UINT retVal = 0; if( dir && !dir->idReserved && (dir->idType & 3) ) { - GRPICONDIRENTRY* entry; + GRPCURSORICONDIRENTRY* entry; HDC hdc; UINT palEnts; int colors; @@ -612,7 +628,7 @@ LookupIconIdFromDirectoryEx( ReleaseDC(0, hdc); - entry = (GRPICONDIRENTRY*)CURSORICON_FindBestIcon( (CURSORICONDIR*)dir, + entry = (GRPCURSORICONDIRENTRY*)CURSORICON_FindBestIcon( (CURSORICONDIR*)dir, cxDesired, cyDesired, colors );