9

メモリを一時ファイルに書き込まずに、RIFF アーカイブ/コンテナと記述されている .ani 形式で保存されたアニメーション カーソルをメモリからロードしたい。これまでのところ、 CreateIconFromResourceEx LookupIconIdFromDirectoryExを使用して、.ani ファイル構造を解析し、個々のフレームを通常のアイコンとして読み込むことができました。

立証が困難な問題の 1 つは、これらのフレームとアニメーション データ (jiffy-rate など) の実際の構成です。これを行うためのエントリが Windows API にないようです。この件に関する文書化または文書化された知識は、アニメーション化されていないアイコン/カーソルをメモリからロードすることに限定されているようです。

「埋め込みアニメーション カーソルをリソースから読み込む」などの同様の質問は、埋め込み可能なリソースからアニメーション カーソルを読み込みたいという要望を表しています。ただし、それから実行可能なソリューションを再現することもできません。Visual Studio 2008 および 2010 のリソース コンパイラが .ani ファイル (ico と cur のみ) をサポートしていないため、それを埋め込むと、.複数のリソースに分解される cur および .ico ファイル。両方の回答に示されているように、CreateIconFromResource への後続の呼び出しは機能しません。これが期待するデータは、RIFF ベースのファイル構造ではなく、アイコン アーカイブ内の単一のディレクティブのアイコン/カーソル データであるためです。

要約すると、アニメーション カーソル (メモリ内) の構造、または目標を追求するのに役立つその他の関連ポインターに関する情報に興味があります。

4

2 に答える 2

7

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);
}
于 2012-08-01T00:28:01.493 に答える
1

アニメーション カーソルをカスタム リソースとしてインポートします。「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;
}
于 2012-07-31T21:32:15.223 に答える