Patch by Jonathon Wilson: Implemented loading cursors with LoadImage()
authorThomas Bluemel <thomas@reactsoft.com>
Wed, 20 Aug 2003 14:08:19 +0000 (14:08 +0000)
committerThomas Bluemel <thomas@reactsoft.com>
Wed, 20 Aug 2003 14:08:19 +0000 (14:08 +0000)
svn path=/trunk/; revision=5702

reactos/include/win32k/cursoricon.h
reactos/lib/user32/user32.def
reactos/lib/user32/user32.edf
reactos/lib/user32/windows/bitmap.c
reactos/lib/user32/windows/icon.c

index e7f0fde..a5a233b 100644 (file)
@@ -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;                             // 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)
+    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   wWidth;                             //Width, in pixels of the cursor image
-    WORD   wHeight;                            //Hight, in pixles of the cursor image
+    WORD   wXHotspot;                          // Number of Color Planes in the XOR image
+    WORD   wYHotspot;                  // Bits per pixel in the XOR image
 } CURSORDIR __attribute__((packed));
 
 typedef struct
-{   union
+{
+    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)
+       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
index 239a3cb..3ec7d4a 100644 (file)
@@ -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
index 49c531e..7f3a33a 100644 (file)
@@ -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
index 42e45a5..e02379e 100644 (file)
@@ -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 <stdlib.h>
 
 /*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;
 }
index f36b85e..bce2ac6 100644 (file)
@@ -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 );