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);
}
Đâ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 ý. –