[8/10] user: Fix loading of .cur cursors

H. Verbeet hverbeet at gmail.com
Sat Aug 5 16:40:28 CDT 2006


  - When loading a cursor, the hotspot should be scaled as well as the image.
  - Allow multicolor cursors
  - Don't use CreateIconFromResourceEx() to load .cur cursors, it
doesn't handle the hotspot correctly. Instead, use load_cursor_frame()
directly.
-------------- next part --------------
diff --git a/dlls/user/cursoricon.c b/dlls/user/cursoricon.c
index 4b498da..6fe12b0 100644
--- a/dlls/user/cursoricon.c
+++ b/dlls/user/cursoricon.c
@@ -1050,6 +1050,13 @@ static BOOL load_cursor_frame( LPBYTE bi
     DoStretch = (bmi->bmiHeader.biHeight/2 != height) ||
       (bmi->bmiHeader.biWidth != width);
 
+    /* Scale the hotspot */
+    if (DoStretch && hotspot.x != ICON_HOTSPOT && hotspot.y != ICON_HOTSPOT)
+    {
+        hotspot.x = (hotspot.x * width) / bmi->bmiHeader.biWidth;
+        hotspot.y = (hotspot.y * height) / (bmi->bmiHeader.biWidth / 2);
+    }
+
     if (!screen_dc) screen_dc = CreateDCW( DISPLAYW, NULL, NULL, NULL );
     if (screen_dc)
     {
@@ -1075,14 +1082,7 @@ static BOOL load_cursor_frame( LPBYTE bi
             /* Create the XOR bitmap */
 
             if (DoStretch) {
-                if(bIcon)
-                {
-                    hXorBits = CreateCompatibleBitmap(screen_dc, width, height);
-                }
-                else
-                {
-                    hXorBits = CreateBitmap(width, height, 1, 1, NULL);
-                }
+                hXorBits = CreateCompatibleBitmap(screen_dc, width, height);
                 if(hXorBits)
                 {
                 HBITMAP hOld;
@@ -1250,9 +1250,11 @@ static HICON CURSORICON_LoadFromFile( LP
                              BOOL fCursor, UINT loadflags)
 {
     CURSORICONFILEDIRENTRY *entry;
+    cursor_frame_t frame = {0};
     CURSORICONFILEDIR *dir;
     DWORD filesize = 0;
     HICON hIcon = 0;
+    POINT16 hotspot;
     LPBYTE bits;
 
     TRACE("loading %s\n", debugstr_w( filename ));
@@ -1261,6 +1263,12 @@ static HICON CURSORICON_LoadFromFile( LP
     if (!bits)
         return hIcon;
 
+    /* If the data contains the magic for an .ICO it's an .ICO,
+     * regardless of what fCursor says. */
+    if (!memcmp( bits, "\x00\x00\x01\x00", 4 )) fCursor = FALSE;
+    /* Same thing for .CUR */
+    else if (!memcmp( bits, "\x00\x00\x02\x00", 4 )) fCursor = TRUE;
+
     dir = (CURSORICONFILEDIR*) bits;
     if ( filesize < sizeof(*dir) )
         goto end;
@@ -1269,7 +1277,7 @@ static HICON CURSORICON_LoadFromFile( LP
         goto end;
 
     if ( fCursor )
-        entry = CURSORICON_FindBestCursorFile( dir, width, height, 1 );
+        entry = CURSORICON_FindBestCursorFile( dir, width, height, colors );
     else
         entry = CURSORICON_FindBestIconFile( dir, width, height, colors );
 
@@ -1282,8 +1290,23 @@ static HICON CURSORICON_LoadFromFile( LP
     if ( entry->dwDIBOffset + entry->dwDIBSize > filesize )
         goto end;
 
-    hIcon = CreateIconFromResourceEx( &bits[entry->dwDIBOffset], entry->dwDIBSize,
-                                      !fCursor, 0x00030000, width, height, loadflags );
+    if ( fCursor )
+    {
+        hotspot.x = entry->xHotspot;
+        hotspot.y = entry->yHotspot;
+    }
+    else
+    {
+        hotspot.x = ICON_HOTSPOT;
+        hotspot.y = ICON_HOTSPOT;
+    }
+
+    hIcon = create_cursor( 1, 0 );
+    load_cursor_frame( &bits[entry->dwDIBOffset], entry->dwDIBSize, hotspot,
+                               0x00030000, width, height, loadflags, &frame );
+    set_cursor_frame( hIcon, 0, &frame );
+    HeapFree( GetProcessHeap(), 0, frame.bits );
+
 end:
     TRACE("loaded %s -> %p\n", debugstr_w( filename ), hIcon );
     UnmapViewOfFile( bits );


More information about the wine-patches mailing list