2012-07-31 8 views
7

Desidero caricare un cursore animato memorizzato in formato .ani, descritto come un archivio/contenitore RIFF, dalla memoria senza scrivere la memoria in un file temporaneo. Finora sono in grado di analizzare la struttura dei file ANI e caricare i singoli frame come icona normale con l'aiuto di CreateIconFromResourceExLookupIconIdFromDirectoryExCarica un cursore animato in fase di esecuzione dalla memoria

Uno dei problemi che le prove difficili è la composizione effettiva di questi fotogrammi e dei dati di animazione (jiffy-rate, ecc.) in quanto sembra che non ci siano voci nell'API di Windows per farlo. La documentazione o la conoscenza scritta sull'argomento sembra essere limitata al caricamento di icone/cursori non animati dalla memoria.

Domande simili come 'Load an embedded animated Cursor from the Resource' esprimono il desiderio di caricare un cursore animato da una risorsa incorporabile. Tuttavia non sono in grado di riprodurre una soluzione praticabile da quello neanche. In parte perché il compilatore di risorse in Visual Studio 2008 & 2010 non supporta i file .ani (solo ico e cur) e quindi li incorpora semplicemente in una copia 1: 1 dei byte come nel file originale anziché in. file cur e .ico che vengono decomposti in più risorse. La successiva chiamata a CreateIconFromResource come mostrato in entrambe le risposte non funziona perché i dati che si aspetta sono i dati dell'icona/cursore di una singola direttiva in un archivio di icone e non una struttura di file basata su RIFF.

Per riassumere sono interessato a qualsiasi informazione riguardante le strutture dei cursori animati (in memoria) o in altri indicatori pertinenti che potrebbero aiutarmi a perseguire il mio obiettivo.

risposta

5

Dopo rivalutando caricamento di un cursore animato da una risorsa incorporabile come sottolinea mfc Ho trovato una soluzione che permette di caricare il cursori da un indirizzo di memoria arbitrario.

I dati da una risorsa incorporabile e i dati letti da un file in memoria sono esattamente identici. Pertanto suggerisce che CreateIconFromResource dovrebbe funzionare anche su memoria normale normale. Tuttavia c'è una differenza fondamentale. La memoria delle risorse incorporabili risiede in sezioni speciali nell'eseguibile che vengono spesso riempite al limite di 4096 byte più vicino. La memoria allocata in fase di esecuzione contiene valori obsoleti.

Ora la soluzione che ho trovato funzionante sfrutta questo semplicemente allocando una banda di guardia di byte pieni di zero. Nei miei casi di test ho scoperto che 8 è il minimo che è anche la dimensione di un chunk nel contenitore riff. Coincidenza? Quello che sospetto è che questo sia un bug e che l'algoritmo funzioni per risorse incorporabili a causa delle sue restrizioni di allineamento all'interno della DLL/eseguibile.

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; 

Ecco una panoramica dei diversi modi per caricare un cursori animati.

#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); 
} 
1

Importare il cursore animato come risorsa personalizzata. Assegnare un nome testuale, ad es. "MyType". Poi caricare il cursore con:

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; 
} 
+0

Questa è una soluzione che sono sicuro che funziona per la maggior parte delle persone. Tuttavia è ancora un'alternativa a quello che sto veramente cercando. Una parte fondamentale di questa domanda è la capacità di caricarlo da una memoria arbitraria. –

Problemi correlati