Create Component : TImage ne s'affiche pas [Résolu]

Messages postés
9
Date d'inscription
mardi 10 octobre 2006
Dernière intervention
20 décembre 2013
-
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.

Merci à Tous et bonnes fêtes de fin d'année...
Afficher la suite 

Votre réponse

1 réponse

Messages postés
1293
Date d'inscription
mardi 28 octobre 2003
Statut
Contributeur
Dernière intervention
3 juillet 2015
0
Merci
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.

Commenter la réponse de sp40

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.