Erich Hoover : user32: Permit loading animated cursors with CreateIconFromResource(Ex).
Alexandre Julliard
julliard at winehq.org
Mon Mar 7 12:22:47 CST 2011
Module: wine
Branch: master
Commit: 7b0ab606e24159e76dec0b309513c18dca4f52df
URL: http://source.winehq.org/git/wine.git/?a=commit;h=7b0ab606e24159e76dec0b309513c18dca4f52df
Author: Erich Hoover <ehoover at mines.edu>
Date: Sat Mar 5 22:34:15 2011 -0700
user32: Permit loading animated cursors with CreateIconFromResource(Ex).
---
dlls/user32/cursoricon.c | 4 +
dlls/user32/tests/cursoricon.c | 160 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 164 insertions(+), 0 deletions(-)
diff --git a/dlls/user32/cursoricon.c b/dlls/user32/cursoricon.c
index cd7d3ed..1139256 100644
--- a/dlls/user32/cursoricon.c
+++ b/dlls/user32/cursoricon.c
@@ -1120,6 +1120,10 @@ HICON WINAPI CreateIconFromResourceEx( LPBYTE bits, UINT cbSize,
return 0;
}
+ /* Check if the resource is an animated icon/cursor */
+ if (!memcmp(bits, "RIFF", 4))
+ return CURSORICON_CreateIconFromANI( bits, cbSize, width, height, 0 /* default depth */, cFlag );
+
if (bIcon)
{
hotspot.x = width / 2;
diff --git a/dlls/user32/tests/cursoricon.c b/dlls/user32/tests/cursoricon.c
index da748b6..8d6ceb7 100644
--- a/dlls/user32/tests/cursoricon.c
+++ b/dlls/user32/tests/cursoricon.c
@@ -54,6 +54,135 @@ typedef struct
CURSORICONFILEDIRENTRY idEntries[1];
} CURSORICONFILEDIR;
+#define RIFF_FOURCC( c0, c1, c2, c3 ) \
+ ( (DWORD)(BYTE)(c0) | ( (DWORD)(BYTE)(c1) << 8 ) | \
+ ( (DWORD)(BYTE)(c2) << 16 ) | ( (DWORD)(BYTE)(c3) << 24 ) )
+
+#define ANI_RIFF_ID RIFF_FOURCC('R', 'I', 'F', 'F')
+#define ANI_LIST_ID RIFF_FOURCC('L', 'I', 'S', 'T')
+#define ANI_ACON_ID RIFF_FOURCC('A', 'C', 'O', 'N')
+#define ANI_anih_ID RIFF_FOURCC('a', 'n', 'i', 'h')
+#define ANI_seq__ID RIFF_FOURCC('s', 'e', 'q', ' ')
+#define ANI_fram_ID RIFF_FOURCC('f', 'r', 'a', 'm')
+#define ANI_icon_ID RIFF_FOURCC('i', 'c', 'o', 'n')
+
+#define ANI_FLAG_ICON 0x1
+#define ANI_FLAG_SEQUENCE 0x2
+
+typedef struct {
+ DWORD header_size;
+ DWORD num_frames;
+ DWORD num_steps;
+ DWORD width;
+ DWORD height;
+ DWORD bpp;
+ DWORD num_planes;
+ DWORD display_rate;
+ DWORD flags;
+} ani_header;
+
+typedef struct {
+ BYTE data[32*32*4];
+} ani_data32x32x32;
+
+typedef struct {
+ CURSORICONFILEDIR icon_info; /* animated cursor frame information */
+ BITMAPINFOHEADER bmi_header; /* animated cursor frame header */
+ ani_data32x32x32 bmi_data; /* animated cursor frame DIB data */
+} ani_frame32x32x32;
+
+typedef struct {
+ DWORD chunk_id; /* ANI_anih_ID */
+ DWORD chunk_size; /* actual size of data */
+ ani_header header; /* animated cursor header */
+} riff_header_t;
+
+typedef struct {
+ DWORD chunk_id; /* ANI_LIST_ID */
+ DWORD chunk_size; /* actual size of data */
+ DWORD chunk_type; /* ANI_fram_ID */
+} riff_list_t;
+
+typedef struct {
+ DWORD chunk_id; /* ANI_icon_ID */
+ DWORD chunk_size; /* actual size of data */
+ ani_frame32x32x32 data; /* animated cursor frame */
+} riff_icon32x32x32_t;
+
+typedef struct {
+ DWORD chunk_id; /* ANI_RIFF_ID */
+ DWORD chunk_size; /* actual size of data */
+ DWORD chunk_type; /* ANI_ACON_ID */
+ riff_header_t header; /* RIFF animated cursor header */
+ riff_list_t frame_list; /* RIFF animated cursor frame list info */
+ riff_icon32x32x32_t frames[1]; /* array of animated cursor frames */
+} riff_cursor_t;
+
+riff_cursor_t empty_anicursor = {
+ ANI_RIFF_ID,
+ sizeof(empty_anicursor) - sizeof(DWORD)*2,
+ ANI_ACON_ID,
+ {
+ ANI_anih_ID,
+ sizeof(ani_header),
+ {
+ sizeof(ani_header),
+ 1, /* frames */
+ 1, /* steps */
+ 32, /* width */
+ 32, /* height */
+ 32, /* depth */
+ 1, /* planes */
+ 10, /* display rate in jiffies */
+ ANI_FLAG_ICON /* flags */
+ }
+ },
+ {
+ ANI_LIST_ID,
+ sizeof(riff_icon32x32x32_t)*1 + sizeof(DWORD),
+ ANI_fram_ID,
+ },
+ {
+ {
+ ANI_icon_ID,
+ sizeof(ani_frame32x32x32),
+ {
+ {
+ 0x0, /* reserved */
+ 0, /* type: icon(1), cursor(2) */
+ 1, /* count */
+ {
+ {
+ 32, /* width */
+ 32, /* height */
+ 0, /* color count */
+ 0x0, /* reserved */
+ 16, /* x hotspot */
+ 16, /* y hotspot */
+ sizeof(ani_data32x32x32), /* DIB size */
+ sizeof(CURSORICONFILEDIR) /* DIB offset */
+ }
+ }
+ },
+ {
+ sizeof(BITMAPINFOHEADER), /* structure for DIB-type data */
+ 32, /* width */
+ 32*2, /* actual height times two */
+ 1, /* planes */
+ 32, /* bpp */
+ BI_RGB, /* compression */
+ 0, /* image size */
+ 0, /* biXPelsPerMeter */
+ 0, /* biYPelsPerMeter */
+ 0, /* biClrUsed */
+ 0 /* biClrImportant */
+ },
+ { /* DIB data: left uninitialized */ }
+ }
+ }
+ }
+};
+
#include "poppack.h"
static char **test_argv;
@@ -1129,6 +1258,37 @@ static void test_CreateIconFromResource(void)
* ok(handle == NULL, "Invalid pointer accepted (%p)\n", handle);
*/
HeapFree(GetProcessHeap(), 0, hotspot);
+
+ /* Test creating an animated cursor. */
+ empty_anicursor.frames[0].data.icon_info.idType = 2; /* type: cursor */
+ empty_anicursor.frames[0].data.icon_info.idEntries[0].xHotspot = 3;
+ empty_anicursor.frames[0].data.icon_info.idEntries[0].yHotspot = 3;
+ handle = CreateIconFromResource((PBYTE) &empty_anicursor, sizeof(empty_anicursor), FALSE, 0x00030000);
+ ok(handle != NULL, "Create cursor failed.\n");
+
+ /* Test the animated cursor's information. */
+ SetLastError(0xdeadbeef);
+ ret = GetIconInfo(handle, &icon_info);
+ ok(ret, "GetIconInfo() failed.\n");
+ error = GetLastError();
+ ok(error == 0xdeadbeef, "Last error: %u\n", error);
+
+ if (ret)
+ {
+ ok(icon_info.fIcon == FALSE, "fIcon != FALSE.\n");
+ ok(icon_info.xHotspot == 3, "xHotspot is %u.\n", icon_info.xHotspot);
+ ok(icon_info.yHotspot == 3, "yHotspot is %u.\n", icon_info.yHotspot);
+ ok(icon_info.hbmColor != NULL || broken(!icon_info.hbmColor) /* no color cursor support */,
+ "No hbmColor!\n");
+ ok(icon_info.hbmMask != NULL, "No hbmMask!\n");
+ }
+
+ /* Clean up. */
+ SetLastError(0xdeadbeef);
+ ret = DestroyCursor(handle);
+ ok(ret, "DestroyCursor() failed.\n");
+ error = GetLastError();
+ ok(error == 0xdeadbeef, "Last error: %u\n", error);
}
static HICON create_test_icon(HDC hdc, int width, int height, int bpp,
More information about the wine-cvs
mailing list