从内存加载运行时的animation光标

我想从内存中加载一个以.ani格式存储的animation光标,该格式被描述为RIFF存档/容器,而无需将内存写入临时文件。 到目前为止,我能够parsing.ani文件结构,并借助于CreateIconFromResourceEx LookupIconIdFromDirectoryEx作为正常图标加载各个帧

难以certificate的问题之一是这些帧的实际组成和animation数据(jiffy-rate等),因为在Windows API中似乎没有条目来这样做。 关于主题的文档或书面知识似乎仅限于从内存加载非animation图标/光标。

类似的问题,例如“从资源中加载embedded的animation光标”expression了从embedded式资源加载animation光标的愿望。 不过,我无法从中重现一个可行的解决scheme。 部分原因是Visual Studio 2008&2010中的资源编译器不支持.ani(仅包含ico和cur)文件,因此embedded它只会导致1:1的字节副本,与原始文件中的字节相反。 cur和.ico文件被分解成多个资源。 随后对两个答案中显示的CreateIconFromResource的调用不起作用,因为它期望的数据是图标存档中单个指令的图标/光标数据,而不是基于RIFF的文件结构。

总结一下,我对任何有关animation游标结构(内存)的信息感兴趣,或者可能有助于我追求目标的相关指针。

在重新评估从mfc指出的嵌入式资源加载动画光标后,我找到了一个解决方案,允许我从任意内存地址加载游标。

来自嵌入式资源的数据和从文件读取到内存中的数据完全相同。 因此,它表明CreateIconFromResource也应该在正常的内存上工作。 但是有一个根本的区别。 可嵌入资源的内存驻留在可执行文件中的特殊部分,通常填充到最近的4096字节边界。 在运行时分配的内存包含垃圾值。

现在我发现的解决方案是通过简单地分配零填充字节的保护带来利用这一点。 在我自己的测试案例中,我发现8是riff容器中块的大小的最小值。 巧合? 我怀疑是这是一个错误,并且算法发生在可嵌入的资源中,因为它在dll / executable中是对齐限制的。

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 = GetmoduleeHandle(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=GetmoduleeHandle(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); } 

将您的动画光标作为自定义资源导入。 给它一个文本名称,例如“MyType”。 然后加载光标:

 HCURSOR hCursor = LoadAnimatedCursor(IDR_MYTYPE1, _T("MyType")); /* ======================================================== */ HCURSOR LoadAnimatedCursor(UINT nID, LPCTSTR pszResouceType) { HCURSOR hCursor = NULL; HINSTANCE hInstance = AfxGetInstanceHandle(); if (hInstance) { HRSRC hResource = FindResource(hInstance, MAKEINTRESOURCE(nID), pszResouceType); DWORD dwResourceSize = SizeofResource(hInstance, hResource); if (dwResourceSize>0) { HGLOBAL hRsrcGlobal = LoadResource(hInstance, hResource); if (hRsrcGlobal) { LPBYTE pResource = (LPBYTE)LockResource(hRsrcGlobal); if (pResource) { hCursor = (HCURSOR)CreateIconFromResource(pResource, dwResourceSize, FALSE, 0x00030000); UnlockResource(pResource); } FreeResource(hRsrcGlobal); } } } return hCursor; }