mfc によって指摘されたように、埋め込み可能なリソースからアニメーション化されたカーソルをロードすることを再評価した後、任意のメモリ アドレスからカーソルをロードできるソリューションを見つけました。
組み込み可能なリソースからのデータと、ファイルからメモリに読み込まれたデータはまったく同じです。そのため、CreateIconFromResourceは通常の通常のメモリでも機能する必要があることが示唆されています。ただし、根本的な違いが 1 つあります。埋め込み可能なリソースのメモリは、実行可能ファイルの特別なセクションに存在し、多くの場合、最も近い 4096 バイト境界までパディングされます。実行時に割り当てられたメモリには、ガベージ値が含まれています。
今私が見つけた解決策は、ゼロで埋められたバイトのガードバンドを割り当てるだけでこれを悪用します。私自身のテスト ケースでは、8 が最小値であり、リフ コンテナー内のチャンクのサイズでもあることがわかりました。一致?私が疑うのは、これはバグであり、アルゴリズムは、dll/実行可能ファイル内の配置制限のために、埋め込み可能なリソースに対してたまたま機能することです。
const int guardbandSize = 8;
FILE* fs = fopen("action.ani", "rb");
fseek(fs, 0,SEEK_END); int dwSize = ftell(fs); fseek(fs, 0,SEEK_SET);
char* memory = new char[dwSize + guardbandSize];
fread(memory, 1, dwSize, fs); memset(memory + dwSize, 0, guardbandSize);
fclose(fs);
cursor = (HCURSOR)CreateIconFromResource((PBYTE)memory,dwSize,FALSE,0x00030000);
delete memory;
以下は、アニメーション化されたカーソルをロードするさまざまな方法の概要です。
#include <Windows.h>
#include <stdio.h>
#include "resource2.h"
void* hWnd;
bool visible = true;
bool running = true;
LRESULT CALLBACK WndProcInternal( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) ;
HCURSOR cursor = 0;
void main()
{
//Setup configuration
const int Width = 640, Height = 480;
const int Method = 4;
//Setup window class
WNDCLASS wcd;
wcd.style = CS_PARENTDC | CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wcd.lpfnWndProc = (WNDPROC)WndProcInternal;
wcd.cbClsExtra = 0;
wcd.cbWndExtra = 0;
wcd.hInstance = GetModuleHandle(NULL);
wcd.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wcd.hCursor = LoadCursor(NULL, IDC_ARROW);
wcd.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
wcd.lpszMenuName = NULL;
wcd.lpszClassName = TEXT("AnimatedIcon");
//Register the window class
if(!RegisterClass(&wcd))
{
MessageBox(NULL, TEXT("Window Registration Failed!"), TEXT("Error!"),MB_ICONEXCLAMATION | MB_OK);
FatalExit(-1);
}
//Create a window
if (!(hWnd=CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("AnimatedIcon"), TEXT("AnimatedIcon"),
WS_VISIBLE | WS_CAPTION | WS_MINIMIZEBOX | WS_THICKFRAME | WS_MAXIMIZEBOX | WS_SYSMENU,
0, 0, Width, Height, NULL, NULL, NULL, NULL)))
{
MessageBoxA(NULL,"Window Creation Error.","ERROR",MB_OK|MB_ICONEXCLAMATION);
FatalExit(-1);
}
if( Method == 1 )
{
//Method 1: Load cursor directly from a file
cursor = LoadCursorFromFileA("action.ani");
}
if( Method == 2 )
{
//Method 2: Load cursor from an resource section in the executable.
cursor = LoadCursor(0, MAKEINTRESOURCE(IDR_ANICURSORS1));
}
if( Method == 3 )
{
//Method 3: Manually locate the resource section in the executable & create the cursor from the memory.
HINSTANCE hInst=GetModuleHandle(0);
HRSRC hRes=FindResourceA(hInst,MAKEINTRESOURCEA(IDR_ANICURSORS1),"ANICURSORS");
DWORD dwSize=SizeofResource(hInst,hRes);
HGLOBAL hGlob=LoadResource(hInst,hRes);
LPBYTE pBytes=(LPBYTE)LockResource(hGlob);
cursor = (HCURSOR)CreateIconFromResource(pBytes,dwSize,FALSE,0x00030000);
}
if( Method == 4 )
{
//Method 4: Load the cursor from a file into memory & create the cursor from the memory.
const int guardbandSize = 8;
FILE* fs = fopen("action.ani", "rb");
fseek(fs, 0,SEEK_END); int dwSize = ftell(fs); fseek(fs, 0,SEEK_SET);
char* memory = new char[dwSize + guardbandSize];
fread(memory, 1, dwSize, fs); memset(memory + dwSize, 0, guardbandSize);
fclose(fs);
cursor = (HCURSOR)CreateIconFromResource((PBYTE)memory,dwSize,FALSE,0x00030000);
delete memory;
}
//Set the cursor for the window and display it.
SetClassLong((HWND)hWnd, GCL_HCURSOR, (LONG)cursor);
while (running)
{
MSG wmsg;
if (PeekMessage(&wmsg, (HWND)hWnd, 0, 0, PM_REMOVE))
{
TranslateMessage(&wmsg);
DispatchMessage(&wmsg);
}
}
}
LRESULT CALLBACK WndProcInternal( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if( uMsg == WM_DESTROY )
{
PostQuitMessage(1);
running = false;
}
return (long)DefWindowProc((HWND)hWnd,uMsg,(WPARAM)wParam,(LPARAM)lParam);
}