tuss
Messages postés9Date d'inscriptionmardi 10 octobre 2006StatutMembreDernière intervention20 décembre 2013
-
Modifié par tuss le 20/12/2013 à 23:06
sp40
Messages postés1276Date d'inscriptionmardi 28 octobre 2003StatutContributeurDernière intervention 3 juillet 2015
-
23 déc. 2013 à 10:26
Bonjour à Tous...
J'ai créé un composant TSprite, dérivé de TImage encapsulant un TTimer, avec une propriété ImageList pour y stocker des images.
Je pose sur mon formulaire, mon composant Sprite1. (pas d'erreur)
Je pose sur ce même formulaire un composant ImageListe1 chargé avec des images.
Je fait pointer la propriété ImageList de mon composant Spite1 sur ImageListe1. (pas d'erreur)
Je met en route mon composant Sripte avec sa propriété Active (Timer.enabled...) (pas d'erreur)
Mais mon composant Sprite(TImage) reste vide, rien ne se dessine. Par défaut il devrait m'afficher la première image du ImageList1.
Mon Composant fontionne, car si je regarde sa propriété Picture elle se met bien à jour et les image change.
Pourquoi mon composant Sprite(TImage) n'affiche rien ?.
Voici mon code :
unit Sprite; //############################################################################ interface //############################################################################ uses SysUtils,Windows,Messages, Classes,Graphics,Controls, ExtCtrls, ThreadComponent; //############################################################################ type TSprite = class(TImage) private Animation: TTimer; FImageList: TImageList; FInterval: cardinal; FActive: boolean; NumImage: integer; procedure SetImageList(Valeur:TImageList); procedure SetInterval(Valeur:cardinal); procedure SetActive(Valeur:boolean); //############################################################################ protected procedure Paint; override; Procedure SetAnimation(Sender:TObject); //############################################################################ public constructor Create(AOwner: TComponent); override; destructor Destroy;override; procedure Notification(AComponent: TComponent; Operation: TOperation); override; //############################################################################ published property ImageList:TImageList read FImageList write SetImageList; property Interval:cardinal read FInterval write SetInterval; property Active:boolean read FActive write SetActive; end; //############################################################################ procedure Register; //############################################################################ implementation //############################################################################ constructor TSprite.Create(AOwner: TComponent); begin inherited Create(AOwner); //Doublebuffered:=true; FImageList:= nil; Picture:=nil; FInterval:=1000; Animation:=TTimer.Create(Self); Animation.OnTimer:=SetAnimation; Animation.Interval:=FInterval; Animation.enabled:=false; NumImage:=0; end; //############################################################################ destructor TSprite.Destroy; begin if Assigned(FImageList) then FImageList.RemoveFreeNotification(Self); Animation.Free; inherited; end; //############################################################################ procedure TSprite.Notification(AComponent: TComponent; Operation: TOperation); begin if (aComponent = FImageList) and (Operation = opRemove) then FImageList:= nil else inherited Notification(AComponent, Operation); end; //############################################################################ procedure TSprite.SetAnimation; begin NumImage:=NumImage+1; if NumImage=FImageList.count-1 then NumImage:=0; Invalidate; end; //############################################################################ procedure TSprite.SetImageList(Valeur:TImageList); begin if Valeur <> FImageList then begin if Assigned(FImageList) then FImageList.RemoveFreeNotification(Self);
FImageList:= Valeur; if Assigned(FImageList) then begin FImageList.FreeNotification(Self); Update; invalidate; end; end; end; //############################################################################ procedure TSprite.SetInterval(Valeur: cardinal); begin if FInterval <> Valeur then begin FInterval:= Valeur; Update; invalidate; end; end; //############################################################################ procedure TSprite.SetActive(Valeur: boolean); begin if FActive <> Valeur then begin FActive:= Valeur; Update; invalidate; Animation.enabled:=FActive; end; end; //############################################################################ procedure TSprite.Paint; begin if Assigned(FImageList) then FImageList.GetBitmap(NumImage,Picture.Bitmap); end; //############################################################################ procedure Register; begin RegisterComponents('MesCompo', [TSprite]); end; //############################################################################ end.
sp40
Messages postés1276Date d'inscriptionmardi 28 octobre 2003StatutContributeurDernière intervention 3 juillet 201515 23 déc. 2013 à 10:26
Salut,
Je te propose les quelques corrections ci dessous. Attention, il reste un peu de travail (notamment sur le Create)
unit Sprite;
//############################################################################
interface
//############################################################################
uses
SysUtils,Windows,Messages, Classes,Graphics,Controls, ExtCtrls; // unité inutilisée : ThreadComponent;
//############################################################################
type
TSprite = class(TImage)
private
Animation: TTimer;
FImageList: TImageList;
FInterval: cardinal;
FActive: boolean;
NumImage: integer;
procedure SetImageList(Valeur:TImageList);
procedure SetInterval(Valeur:cardinal);
procedure SetActive(Valeur:boolean);
//############################################################################
protected
{
procedure Paint; override;
Suppression de la surcharge de la méthode Paint car, selon l'aide de Delphi :
"Telle qu'implémentée dans TGraphicControl, Paint ne fait rien."
Et relocalisation du code d'affichage dans le déclenchement du timer
}
Procedure SetAnimation(Sender:TObject);
//############################################################################
public
constructor Create(AOwner: TComponent); override;
destructor Destroy;override;
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
//############################################################################
published
property ImageList:TImageList read FImageList write SetImageList;
property Interval:cardinal read FInterval write SetInterval;
property Active:boolean read FActive write SetActive;
end;
//############################################################################
procedure Register;
//############################################################################
implementation
//############################################################################
constructor TSprite.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
//Doublebuffered:=true;
{
Il faut indiquer au composant le composant parent.
Ici je fais un cast un peu brutal... Il faut que tu gères ça
plus proprement et vérifier si le cast peut passer...
}
Parent := TWinControl(AOwner);
FImageList:= nil;
Picture:=nil;
FInterval:=1000;
Animation:=TTimer.Create(Self);
Animation.OnTimer:=SetAnimation;
Animation.Interval:=FInterval;
Animation.enabled:=false;
NumImage:=0;
end;
//############################################################################
destructor TSprite.Destroy;
begin
if Assigned(FImageList) then
FImageList.RemoveFreeNotification(Self);
Animation.Free;
inherited;
end;
//############################################################################
procedure TSprite.Notification(AComponent: TComponent; Operation: TOperation);
begin
if (aComponent = FImageList) and (Operation = opRemove) then
FImageList:= nil
else
inherited Notification(AComponent, Operation);
end;
//############################################################################
procedure TSprite.SetAnimation;
var
{
Assez bizarre, je ne me l'explique pas...
Si on ne passe pas par un bitmap temporaire mais qu'on fait directement :
FImageList.GetBitmap(NumImage, Picture.Bitmap);
Une fois arrivé à la dernière image de l'imagelist, le composant reste
bloqué sur la dernière image qu'il affiche en boucle, alors que le 'NumImage'
varie bien...
}
myBitmap : TBitmap;
begin
Animation.Enabled := False;
NumImage:=NumImage+1;
if NumImage=FImageList.count-1 then NumImage:=0;
myBitmap := TBitmap.Create;
FImageList.GetBitmap(NumImage, myBitmap);
Picture.Bitmap := myBitmap;
myBitmap.Free;
Invalidate;
Animation.Enabled := True;
end;
//############################################################################
procedure TSprite.SetImageList(Valeur:TImageList);
begin
if Valeur <> FImageList then
begin
if Assigned(FImageList) then
FImageList.RemoveFreeNotification(Self);
FImageList:= Valeur;
if Assigned(FImageList) then
begin
FImageList.FreeNotification(Self);
Update;
invalidate;
end;
end;
end;
//############################################################################
procedure TSprite.SetInterval(Valeur: cardinal);
begin
if FInterval <> Valeur then
begin
FInterval:= Valeur;
{
Ici, il faut définir le nouvel intervalle du timer... Sinon, tu restes sur les 1000 millisecondes de ton create...
}
Animation.Interval := FInterval;
Update;
invalidate;
end;
end;
//############################################################################
procedure TSprite.SetActive(Valeur: boolean);
begin
if FActive <> Valeur then
begin
FActive:= Valeur;
Update;
invalidate;
Animation.enabled:=FActive;
end;
end;
//############################################################################
procedure Register;
begin
RegisterComponents('MesCompo', [TSprite]);
end;
//############################################################################
end.