Rappeler une procedure OnMouseUp

Résolu
Warbler69 - 6 janv. 2013 à 01:56
sp40 Messages postés 1276 Date d'inscription mardi 28 octobre 2003 Statut Contributeur Dernière intervention 3 juillet 2015 - 8 janv. 2013 à 14:20
Bonjour,
Dans une application Delphi 2006, j'ai écrit une procédure pour un événement OnMouseUp d'un TImage (un bouton).

procedure TFormMain.ImageMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
Begin
...
end;

Celle-ci fonctionne très bien en réponse à un clic souris sur le TImage.
Mais comment faire pour rappeler ce code à un autre endroit de mon programme ?
En somme, simuler un clic sur cet objet Timage.
Je n'arrive pas à trouver les bons paramètres pour appeler cette procédure.

A l'avance merci pour vos suggestions et ... bonne année 2013 à tous.

Warbler

17 réponses

f0xi Messages postés 4205 Date d'inscription samedi 16 octobre 2004 Statut Modérateur Dernière intervention 12 mars 2022 35
6 janv. 2013 à 02:54
procedure TFormMain.Button1Click(Sender: TObject);
begin
  ImageMouseUp(TObject(Image), [mbLeft], [], 1, 1);
end;

________________________________________________________
besoin de câbles audio, vidèo, informatique pas cher ?
3
dubois77 Messages postés 675 Date d'inscription jeudi 17 avril 2008 Statut Membre Dernière intervention 19 février 2019 14
6 janv. 2013 à 08:29
Salut
ton premier code à cette allure :
procedure TFormMain.ImageMouseUp(Sender: TObject; Button: TMouseButton; 
Shift: TShiftState; X, Y: Integer); 
Begin 
  maProconmouse(para1,para2 ...);
end;

procedure TFormMain.maProconmouse(para1:integer,para2:xxxx ...);
begin
 ....
end;


ensuite il suffit de faire :
procedure TFormMain.Button1Click(Sender: TObject);
begin
  maProconmouse(para1,para2 ...);
end;





Dubois77
site perso
3
Bonjour,
Merci beaucoup pour vos réponses.

J'aurais préféré utiliser la proposition directe de fOxi, mais ça plante toujours au niveau des paramètres ImageMouseUp.
Je suis donc passé par une procédure intermédiaire comme proposé par dubois77 et ça fonctionne.

Je vais essayer de comprendre pourquoi la première proposition ne fonctionne pas.
Bonne journée,
Warbler
3
Caribensila Messages postés 2527 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 16 octobre 2019 18
6 janv. 2013 à 13:07
  var     X, Y : Integer;
  begin
  X := 0;
  Y := 0;
  ImageMouseUp(TObject(Image), mbLeft, [], X, Y);
3

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
korgis Messages postés 420 Date d'inscription samedi 17 mai 2003 Statut Membre Dernière intervention 6 mai 2019 17
6 janv. 2013 à 14:21
ImageMouseUp(nil, mbLeft, [], 0, 0);
3
sp40 Messages postés 1276 Date d'inscription mardi 28 octobre 2003 Statut Contributeur Dernière intervention 3 juillet 2015 15
7 janv. 2013 à 09:34
@Warbler69
J'aurais préféré utiliser la proposition directe de fOxi


Je trouve la solution de M. Dubois plus propre et plus structurée (n'en déplaise à f0xi qui reste de très bon conseil quand même...). D'une manière générale, dès que du code est utilisé plus d'une fois dans un programme, je préfère faire une procédure ou une fonction, plutôt que de bidouiller des appels à des événements de composants. M'enfin, ça n'est qu'un avis...


Simon
3
cs_MAURICIO Messages postés 2106 Date d'inscription mardi 10 décembre 2002 Statut Modérateur Dernière intervention 15 décembre 2014 5
7 janv. 2013 à 10:50
"dès que du code est utilisé plus d'une fois dans un programme, je préfère faire une procédure ou une fonction, plutôt que de bidouiller des appels à des événements de composants"
- C' est une très bon conseil!


Composants Cindy pour Delphi
Faites une donation.
3
Caribensila Messages postés 2527 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 16 octobre 2019 18
7 janv. 2013 à 11:38
Oui, c'est un bon conseil à condition d'être conscient que cela plombe les performances et que, par exemple, c'est à éviter dans les boucles longues.
3
Merci pour vos avis et commentaires.
J'ai adopté la solution "procédure" et ça fonctionne bien.
Cordialement
0
cs_cantador Messages postés 4720 Date d'inscription dimanche 26 février 2006 Statut Modérateur Dernière intervention 31 juillet 2021 13
7 janv. 2013 à 14:13
Bonjour,

pour ma part, je préfère la solution f0xi, Caribensila, Korgis
lorsqu'elle est évènementielle..

cantador
0
sp40 Messages postés 1276 Date d'inscription mardi 28 octobre 2003 Statut Contributeur Dernière intervention 3 juillet 2015 15
7 janv. 2013 à 16:21
@Cari :
J'ai testé ce que tu disais dans l'unité suivante (saint Thomas, c'est moi ! ) :

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    CheckBox1: TCheckBox;
    Edit1: TEdit;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    a : integer;
    procedure calculalacon;
    { Déclarations privées }

  public
    { Déclarations publiques }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button2Click(Sender: TObject);
begin
     Button1Click(self);
end;

procedure TForm1.calculalacon;
var
   i : integer;
begin
     for i := 0 to 100000000
         do inc(a);
     for i := 0 to 100000000
         do dec(a);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
     a := 0;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
   i, j : integer;
   rDuree,
   rStart,
   rEnd : real;
begin
     rStart := now;
     for j := 0 to 30 do begin
         if CheckBox1.Checked
            then calculalacon
         else begin
              for i := 0 to 100000000
                  do inc(a);
              for i := 0 to 100000000
                  do dec(a);
         end;
     end;
     rEnd := now;
     rDuree := rEnd - rStart;
     edit1.Text := FloatToStr(rDuree);
end;

end.


En moyenne, on a 6 centièmes de mieux en cliquant sur le button1 avec la procédure qu'en cliquant sur le button1 sans procédure (uh ?), et on a 4 centièmes de mieux qu'en cliquant sur le button2... J'ai testé sur XE2. Peux tu m'en dire un peu plus sur le plombage des perfs ? (ou c'est mon test qui est pourri ?)

Simon
0
sp40 Messages postés 1276 Date d'inscription mardi 28 octobre 2003 Statut Contributeur Dernière intervention 3 juillet 2015 15
7 janv. 2013 à 16:49
Ça a l'air un peu corsé... Je jetterai un œil dès que possible, promis.
Mon programme de test ne sert à rien, et à priori, il n'y a rien à comprendre... C'est juste pour faire une boucle et tester si un code qui est délocalisé dans une procédure s'exécute plus rapidement ou pas que s'il est dans la boucle.

Simon
0
f0xi Messages postés 4205 Date d'inscription samedi 16 octobre 2004 Statut Modérateur Dernière intervention 12 mars 2022 35
7 janv. 2013 à 21:46
Il n'y a pas de bonne ou mauvaise méthodes.

A savoir que faire du procwarp c'est à double avantage et double désavantage dans l'apprentissage de la programmation :

1er avantage, ça éclaircie le code, le rendant plus compréhensible. à condition de maitriser l'écriture et les conventions de code.

2eme avantage, on sépare mieux les routines des GE, facilement transposable, on peux avoir des procédure multi-evenementielle. à condition de maitriser les principes de polyvalence du code.

1er inconvenance, ça rallonge le code, le rendant plus difficile à parcourir. nécessite d'aller chercher les déclarations (x2) et non d'avoir la routine directement par le biais de l'éditeur d’événement. Il est nécessaire de respecter plusieurs conventions d'écriture et de gestion du code source pour en faciliter la lécture (regrouper les évenements faisant appels au procwarp et mettre ce dernier avant ou aprés ce groupe. Utiliser les Regions de code).

2eme inconvenance, ça génère de nombreux call qui peuvent alourdir le programme voir le rendre peu performant si le procwarpping est abusif.


Dans le cas présent il est intéréssant de le développer :


{ ImagePixel }

function imagePixel(aBitmap: TBitmap; aPixelX, aPixelY: integer): TColor;
begin
  if assigned(aBitmap) then
    result := aBitmap.pixels[aPixelX, aPixelY]; // <-- hahaha lol ... utilise ScanLine hein.
end;

procedure TFormMain.ImageMouseUp(); // Oui !
begin
  LabelMouseSelect.Caption := format('$%.8x', [imagePixel(Image1.Picture.Bitmap, X, Y)]);
end;

procedure TFormMain.ButtonCornerClick(); // Oui !
begin
  LabelLeftTop.Caption     := format('$%.8x', [imagePixel(Image1.Picture.Bitmap, 0, 0)]);
  LabelLeftBottom.Caption  := format('$%.8x', [imagePixel(Image1.Picture.Bitmap, 0, Image1.Picture.Height-1)]);
  LabelRightBottom.Caption := format('$%.8x', [imagePixel(Image1.Picture.Bitmap, Image1.Picture.Width-1, 0)]);
  LabelRightTop.Caption    := format('$%.8x', [imagePixel(Image1.Picture.Bitmap, Image1.Picture.Width-1, Image1.Picture.Height-1)]);
end;

procedure TFormMain.ButtonProcessClick(); // NON ! SURTOUT PAS ! à moins d'aimer les process qui plombes 10 minutes.
var X, Y: integer;
begin
  for Y := 0 to Image1.Picture.Height-1 do
    for X := 0 to Image1.Picture.Width-1 do
      ListBox1.Items.Add(format('$%.8x', [imagePixel(Image1.Picture.Bitmap, X, Y)]));
end;


{ Image Pixels List }
procedure ImagePixelsList(aBitmap: TBitmap; aStrings: TString);
type
  PScanLine = ^TScanLine;
  TScanLine = array[0..0] of integer;
var X, Y, W, H: integer;
    P : PScanLine;
    B: TBitmap;
begin
  if not (assigned(aBitmap) and assigned(aStrings)) then exit;

  W := Image1.Picture.Width-1;
  H := Image1.Picture.Height-1;
  B := TBitmap.Create;
  try
    B.assign(aBitmap);
    B.PixelFormat := pf32bit;
    Strings.BeginUpdate;
    try
      Strings.Clear;
      for Y := 0 to H do
      begin
        P := B.ScanLine[Y];
        for X := 0 to W do
          Strings.Add(format('$%.8x', [P^[X]]));
      end;
    finally
      Strings.EndUpdate;
    end;
  finally
    B.Free;
  end;
end;

procedure TFormMain.ButtonProcessOptimizedClick(); // Oui !
begin
  ImagePixelList(Image1.Picture.Bitmap, ListBox1.Items);
end;



________________________________________________________
besoin de câbles audio, vidèo, informatique pas cher ?
0
Caribensila Messages postés 2527 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 16 octobre 2019 18
8 janv. 2013 à 08:05
...Comme je disais :

« C'est bien mais c'est à éviter dans les boucles longues. »
0
sp40 Messages postés 1276 Date d'inscription mardi 28 octobre 2003 Statut Contributeur Dernière intervention 3 juillet 2015 15
8 janv. 2013 à 09:12
@Cari :
Spécifiquement sous Delphi ou d'une manière générale ?

Simon
0
Caribensila Messages postés 2527 Date d'inscription jeudi 15 janvier 2004 Statut Membre Dernière intervention 16 octobre 2019 18
8 janv. 2013 à 13:02
« @Cari : Spécifiquement sous Delphi ou d'une manière générale ? »


D'une façon générale l'appel d'une procédure ou d'une fonction a toujours un coût.
Mais il se peut que certains compilateurs gèrent nativement plus ou moins bien cela.
Sous Delphi, par exemple, il existe la directive INLINE qui remplace l'appel d'une fonction par le code compilé du corps de la fonction (VOIR Using the inline Directive). Mais, personnellement, je dois mal m'y prendre car je n'ai jamais su mettre en oeuvre cette directive. Ce serait pourtant pratique de favoriser la lisibilité du code sans négliger les performances !


Pour revenir sur ton test, je ne comprenais pas parce que tu y utilises en fait 2 boucles. Une dans le corps de la routine appelante, et l'autre dans la routine appelée. Et ça ne peut donner de bons résultats car l'essentiel des itérations se font dans la routine appelée.
Voici un bout de code qui met bien le principe de réintégration d'une routine dans une boucle en évidence :

procedure TForm1.FormCreate(Sender: TObject);
  begin
  Edit1.Text := '999999';
  Edit2.Text := '999999';
end;

function Cube(X: Integer): Integer;
  begin
  Result := X*X*X;
end;

procedure TForm1.Button1Click(Sender: TObject);
  var     i,C,X : Integer;
          Start, Elapsed : Int64;
  begin
  X := 123;
  Start := GetTickCount;
  for i := 0 to 100000000 do
    C := Cube(X); // <---  !!!
  Elapsed := GetTickCount-Start;
  if StrToInt(Edit1.Text) > Elapsed then Edit1.Text := IntToStr(Elapsed);
  //Meilleur temps: 406 milliseconds.
end;

procedure TForm1.Button2Click(Sender: TObject);
  var     i,C,X : Integer;
          Start, Elapsed : Int64;
  begin
  X := 123;
  Start := GetTickCount;
  for i := 0 to 100000000 do
    C := X*X*X; // <---  !!!
  Elapsed := GetTickCount-Start;
  if StrToInt(Edit2.Text) > Elapsed then Edit2.Text := IntToStr(Elapsed);
  //Meilleur temps: 62 milliseconds (6 fois + rapide!).
end;
0
sp40 Messages postés 1276 Date d'inscription mardi 28 octobre 2003 Statut Contributeur Dernière intervention 3 juillet 2015 15
8 janv. 2013 à 14:20
Ok, je comprends (et c'est un peu plus abordable que vos histoire de pixels... )
Je vais aussi jeter un oeil à INLINE. Merci pour les infos.

Simon
0
Rejoignez-nous