user32: Permit loading animated cursors with CreateIconFromResource(Ex).

This commit is contained in:
Erich Hoover 2011-03-05 22:34:15 -07:00 committed by Alexandre Julliard
parent 3c6de3b348
commit 7b0ab606e2
2 changed files with 164 additions and 0 deletions

View File

@ -1120,6 +1120,10 @@ HICON WINAPI CreateIconFromResourceEx( LPBYTE bits, UINT cbSize,
return 0; 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) if (bIcon)
{ {
hotspot.x = width / 2; hotspot.x = width / 2;

View File

@ -54,6 +54,135 @@ typedef struct
CURSORICONFILEDIRENTRY idEntries[1]; CURSORICONFILEDIRENTRY idEntries[1];
} CURSORICONFILEDIR; } 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" #include "poppack.h"
static char **test_argv; static char **test_argv;
@ -1129,6 +1258,37 @@ static void test_CreateIconFromResource(void)
* ok(handle == NULL, "Invalid pointer accepted (%p)\n", handle); * ok(handle == NULL, "Invalid pointer accepted (%p)\n", handle);
*/ */
HeapFree(GetProcessHeap(), 0, hotspot); 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, static HICON create_test_icon(HDC hdc, int width, int height, int bpp,