开发者

Once again about animation (*.ani) cursors from program resources (Delphi 2010)

开发者 https://www.devze.com 2023-02-21 05:05 出处:网络
I create a resource file, Cur.rc. It contains CUR121\"MYCURSOR.ANI\" mycursor.ani is a file that exists. It\'s a normal .ani animated cursor.

I create a resource file, Cur.rc. It contains

CUR1   21   "MYCURSOR.ANI"

mycursor.ani is a file that exists. It's a normal .ani animated cursor.

I compile the resource file using

Brcc32 cur.rc  

which results in the file cur.res

In Unit1 of my project (I tried the project's .dpr file as well), I added

{$R cur.res} 

In the FormCreate event,

Screen.Cursors[8]:=LoadCursor(HInstance, 'CUR1');
Screen.Cursor := 8;
// p.s. 8 - for an example, can be 0.... n or a constant

I run the application. The cursor should change to my animated cursor.

This should be simple. I've tried several different cursor files from different sources. But it doesn't work.

It works if you load from a file:

Screen.Cursors [8]:=LoadCursorFromFile('d:\1.ani'); 
Screen.Cursor:=8;

How do I load the animated cursor from a resource? Why doesn't it work like loading a normal cursor?


This won't work. Apparently, there's no way to load an animated cursor from a resource without going to a file first.

This works, though:

// MyCursor.rc
BGCURSOR ANICURSOR "D:\TEMP\Background.ani"

// Unit1.pas
{$R My开发者_如何学运维Cursor.res MyCursor.rc}

procedure TForm1.FormCreate(Sender: TObject);
var
  Res: TResourceStream;
  FileName: string;
  HC: HCURSOR;
const
  BGCursor = 8;  // Can be anything from 0..32767
begin
  Res := TResourceStream.Create(MainInstance, 'BGCURSOR', 'ANICURSOR');
  try
    FileName := ExtractFilePath(ParamStr(0)) + 'BGCursor.ani';
    Res.SaveToFile(FileName);
    HC := LoadCursorFromFile(PChar(FileName));
    Screen.Cursors[BGCursor] := HC;
    Screen.Cursor := BGCursor;
  finally
    DeleteFile(FileName);
    Res.Free;
  end;
end;

I write it after two answers because comments do not wish to be applied.

P.S. Wrote on Delphi 2010, but I think, as on Delphi 7 will go.

The basic question:

Works only for Panel1. Initial code in the complete set, here text, if to whom long:

The full example has tried to make:

1. 3 panels - at form start on everyone are appointed the cursor.
2. Works only on the first or at loading of the cursor from a file
3. All in the complete set (the small program, cursors, etc.) - exe (executed) - too there

Initial code in the complete set, here text, if to whom long:

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

Const
  CurConst = 8; // 8 .. example, 8 is like me :)
  CurConst1 = 7;
  CurConst2 = 6;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    Panel2: TPanel;
    Button1: TButton;
    Panel3: TPanel;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  cur: HCursor;

implementation

{$R *.dfm}
{$R My.res}

procedure TForm1.Button1Click(Sender: TObject);
var 
  s: string;
begin
  s:=IncludeTrailingPathDelimiter(extractfilepath(paramstr(0)))+'sc1.ani';
  showmessage('Temp value: '+ s);
  Screen.Cursors[CurConst]:=LoadCursorFromFile(pchar(s));
  panel1.Cursor:=CurConst;
  panel2.Cursor:=CurConst;
  panel3.Cursor:=CurConst;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  // panel 1
  Screen.Cursors[CurConst] := LoadCursor(HInstance,'V_0');
  panel1.Cursor:=CurConst;
  // panel 2
  Screen.Cursors[CurConst1] := LoadCursor(HInstance,'V_1');
  panel2.Cursor := CurConst1;
  // panel 2
  Screen.Cursors[CurConst2] := LoadCursor(HInstance,'V_2');
  panel3.Cursor := CurConst2;
end;

end.

DownLoad (full project code): http://www.sendspace.com/file/jbzrpx (close popup window, look down); mirror: The attention - anything to pay it is not necessary (is downloaded under the slow reference (the size 4 mb)) http://rapidshare.com/files/455515706/TestCursor.zip (no viruses - testing Symantec - 11.6.3000 SEP) In general there an initial code in the complete set - will understand.


Apparently the resource loader of the api is somewhat pickier than the file loader, or the requirements are a bit different.

I was able to make your cursors work in the full project code download you provided, without even touching the code, thanks to the executable included:

  • Open 'sc1.ani' in a hex editor.
  • Locate the second double word in the file (the first is the signature 'RIFF'). The double word is '62 0F 00 00' which is 3938, this is the file size. Modify it to become '5A 0F 00 00', that is '3930', now it denotes the total number of remaining bytes after the length identifier. Save the ani file.
  • Open the executable in 'Resource Hacker' or compatible resource editor, and replace 'V_1' with the modified file.
  • Save the executable and run.


You can use Greenfish Icon Editor to open your animated cursors and then save again. It seems to produce compatible files.


Use the deceivingly named CreateIconFromResource API function.

var
  res: TCustomMemoryStream;
  cur: HCursor;
begin
  res := TResourceStream.Create(MainInstance, 'BGCURSOR', 'ANICURSOR');
  try
    cur := CreateIconFromResource(res.Memory, res.Size, False, $30000);
    Win32Check(cur <> 0);
    Screen.Cursors[8] := cur;
  finally
    res.Free;
  end;
end;


This works for me on Berlin:

To be more specific: If you landed here because you are looking for a way to load animated cursors without first having to save it into a file, this worked for me. The only difference is, move the data to the heap and load it from there.

function GetResourceAsAniCursor(const ResName: string; Width, Height: Integer): HCursor;
var
  resInfo: HRSRC;
  resSize: cardinal;
  resHandle: HGLOBAL;
  resData, Data: pchar;
begin
  Result := 0;
  resInfo := FindResource(MainInstance, PWideChar(ResName), PWideChar('ANICURSOR'));
  resHandle := LoadResource(MainInstance, resInfo);
  if resHandle <> 0 then
  begin
    resSize := SizeofResource(MainInstance, resInfo);
    resData := LockResource(resHandle);
    Data := AllocMem(resSize);
    try
      Move(resData^, Data^, resSize);
      Result := CreateIconFromResourceEx(PByte(Data), resSize, False, $00030000, Width, Height, 0);
    finally
      FreeMem(Data);
    end;
  end;
end;

Usage:

const 
 crMyAniCursor = 1;

 Screen.Cursors[crMyAniCursor] := GetResourceAsAniCursor('MYANICURSOR', 128, 128);


This won't work. Apparently, there's no way to load an animated cursor from a resource without going to a file first.

This works, though:

// MyCursor.rc
BGCURSOR ANICURSOR "D:\TEMP\Background.ani"

// Unit1.pas
{$R MyCursor.res MyCursor.rc}

procedure TForm1.FormCreate(Sender: TObject);
var
  Res: TResourceStream;
  FileName: string;
  HC: HCURSOR;
const
  BGCursor = 8;  // Can be anything from 0..32767
begin
  Res := TResourceStream.Create(MainInstance, 'BGCURSOR', 'ANICURSOR');
  try
    FileName := ExtractFilePath(ParamStr(0)) + 'BGCursor.ani';
    Res.SaveToFile(FileName);
    HC := LoadCursorFromFile(PChar(FileName));
    Screen.Cursors[BGCursor] := HC;
    Screen.Cursor := BGCursor;
  finally
    DeleteFile(FileName);
    Res.Free;
  end;
end;
0

精彩评论

暂无评论...
验证码 换一张
取 消