2012-07-31 50 views
7

Tôi muốn tải con trỏ hoạt ảnh được lưu trữ ở định dạng .ani, được mô tả là lưu trữ/vùng chứa RIFF, từ bộ nhớ mà không ghi bộ nhớ vào tệp tạm thời. Vì vậy, đến nay tôi có thể phân tích cấu trúc tệp .ani và tải các khung riêng lẻ dưới dạng biểu tượng bình thường với sự trợ giúp của CreateIconFromResourceExLookupIconIdFromDirectoryExTải con trỏ hoạt ảnh khi chạy từ bộ nhớ

Một trong những vấn đề chứng minh khó khăn là thành phần thực tế của các khung này và dữ liệu hoạt ảnh (jiffy-rate vv) vì dường như không có mục nhập nào trong API Windows để làm như vậy. Tài liệu hoặc kiến ​​thức bằng văn bản về chủ đề dường như bị giới hạn khi tải các biểu tượng/con trỏ không hoạt hình từ bộ nhớ.

Các câu hỏi tương tự như 'Load an embedded animated Cursor from the Resource' thể hiện mong muốn tải con trỏ hoạt ảnh từ tài nguyên có thể nhúng. Tuy nhiên tôi không thể tái tạo một giải pháp khả thi từ đó. Một phần vì trình biên dịch tài nguyên trong phòng thu trực quan 2008 & 2010 không hỗ trợ các tệp .ani (chỉ ico và cur) và để nhúng nó chỉ đơn giản là kết quả trong bản sao byte 1: 1 như trong tệp gốc trái ngược với. tập tin cur và .ico bị phân tách thành nhiều tài nguyên. Cuộc gọi tiếp theo tới CreateIconFromResource như được hiển thị trong cả hai câu trả lời không hoạt động vì dữ liệu mà nó mong đợi là dữ liệu biểu tượng/con trỏ của một chỉ thị duy nhất trong kho lưu trữ biểu tượng chứ không phải cấu trúc tệp dựa trên RIFF.

Để tóm tắt, tôi quan tâm đến bất kỳ thông tin nào liên quan đến cấu trúc của con trỏ động (trong bộ nhớ) hoặc các con trỏ có liên quan khác có thể giúp tôi theo đuổi mục tiêu của mình.

Trả lời

5

Sau khi đánh giá lại nạp một con trỏ chuột động từ một nguồn tài nguyên có khả năng nhúng như chỉ ra bởi MFC Tôi đã tìm thấy một giải pháp cho phép tôi để nạp con trỏ từ một địa chỉ bộ nhớ tùy ý.

Dữ liệu từ tài nguyên có thể nhúng và dữ liệu được đọc từ tệp vào bộ nhớ giống hệt nhau. Do đó, gợi ý rằng CreateIconFromResource nên hoạt động trên bộ nhớ thông thường. Tuy nhiên có một sự khác biệt cơ bản. Bộ nhớ của các tài nguyên nhúng có thể nằm trong các phần đặc biệt trong tệp thi hành thường được đệm vào ranh giới 4096 byte gần nhất. Bộ nhớ được cấp phát trong thời gian chạy có chứa các giá trị rác.

Bây giờ, giải pháp mà tôi đã tìm cách khai thác công việc này bằng cách phân bổ một băng tần bảo vệ các byte không được lấp đầy. Trong các trường hợp thử nghiệm của riêng tôi, tôi thấy rằng 8 là mức tối thiểu cũng xảy ra là kích thước của một đoạn trong thùng chứa. Trùng hợp ngẫu nhiên? Những gì tôi nghi ngờ là đây là một lỗi và thuật toán sẽ xảy ra để làm việc cho các nguồn tài nguyên nhúng do hạn chế liên kết của nó trong 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; 

Dưới đây là tổng quan về nhiều cách khác nhau để tải một con trỏ động.

#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

Nhập con trỏ hoạt ảnh của bạn làm tài nguyên tùy chỉnh. Đặt tên văn bản, ví dụ: "MyType". Sau đó tải con trỏ với:

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

Đây là giải pháp mà tôi chắc chắn làm việc cho hầu hết mọi người. Tuy nhiên nó vẫn là một thay thế cho những gì tôi đang thực sự tìm kiếm. Một phần cơ bản của câu hỏi này là khả năng tải nó từ một bộ nhớ tùy ý. –

Các vấn đề liên quan