Evènement OnMouseMove inapproprié [Résolu]

Messages postés
1105
Date d'inscription
dimanche 1 août 2004
Dernière intervention
17 août 2008
- 25 févr. 2008 à 15:29 - Dernière réponse :
Messages postés
1105
Date d'inscription
dimanche 1 août 2004
Dernière intervention
17 août 2008
- 26 févr. 2008 à 15:32
Salut à tous !

Je rencontre un problème assez étrange: j'implémente les évènements OnMouseDown et OnMouseMove de ma fiche et lorsque je sélectionne un fichier par double-clic dans un TOpenDialog, la fiche reçoit un évènement OnMouseMove indiquant que le bouton gauche est enfoncé.

Or, aucun évènement OnMouseDown n'a été généré auparavant !

C'est assez problématique car je fais des initialisations dans le OnMouseDown, partant du principe que celui-ci est forcément appelé avant que le OnMouseMove ne soit appelé avec "ssLeft in Shift".
Et ça fait de la corruption de données !

Je voudrais donc savoir si j'ai loupé un truc ou si c'est vraiment un bug de Delphi, auquel cas ça risque d'être assez ennuyant.

NB: notez bien que le problème ne se passe que lors d'un double-clic sur un fichier dans le TOpenDialog, pas si on clique sur "ouvrir".

Merci de bien vouloir m'éclairer,
Flo
Afficher la suite 

Votre réponse

13 réponses

Meilleure réponse
Messages postés
1105
Date d'inscription
dimanche 1 août 2004
Dernière intervention
17 août 2008
- 26 févr. 2008 à 15:32
3
Merci
Au vu de l'incompréhension globale ce ce genre de "bug", je propose une solution (à améliorer) ici :

http://www.delphifr.com/codes/EVENEMENTS-SOURIS-COMMENT-NE-PAS-FAIRE-AVOIR_45864.aspx

Merci florenth 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 89 internautes ce mois-ci

Commenter la réponse de florenth
- 25 févr. 2008 à 17:33
0
Merci
Salut,

Flo désolé mais j'ai rien compris à ta question . J'ai essayé de reproduire ton probleme et aucun evenement OnMouse n'est déclenché quand je sélectionne un fichier via un TOpenDialog
Commenter la réponse de Utilisateur anonyme
Messages postés
1105
Date d'inscription
dimanche 1 août 2004
Dernière intervention
17 août 2008
- 25 févr. 2008 à 18:08
0
Merci
Purée, alors, je viens de refaire le test juste avec un TForm et un TOpenDialog et j'ai bien ce problème.
Il faut bien sûr que le TOpenDialog soit au dessus du TForm.

Le problème:
J'ai un évènement OnMouseMove qui se déclenche avec comme paramètre Shift = [ssLeft] alors qu'aucun évènement MouseDown ne m'a prévenu que le bouton gauche a été enfoncé.
Commenter la réponse de florenth
Messages postés
1105
Date d'inscription
dimanche 1 août 2004
Dernière intervention
17 août 2008
- 25 févr. 2008 à 18:11
0
Merci
Voila juste ce qui suffit à faire planter : on obtient le message 'MouseMove avec bouton gauche enfoncé' mais pas l'autre ! snif !

(NB: il faut sélectionner un fichier par double-clic dans le TOpenDialog)



unit Unit1;

interface

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

type
TForm1 = class(TForm)
OpenDialog1: TOpenDialog;
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
{ Juste pour être sur que le TOpenDialog sera au dessus de la fiche }
SetBounds(0, 0, Screen.Width, Screen.Height);

OpenDialog1.Execute;
end;

procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Button = mbLeft then ShowMessage('Clic gauche');
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
if ssLeft in Shift then ShowMessage('MouseMove avec bouton gauche enfoncé');
end;

end.
Commenter la réponse de florenth
Messages postés
4229
Date d'inscription
vendredi 23 juillet 2004
Dernière intervention
3 août 2018
- 25 févr. 2008 à 18:33
0
Merci
Salut,

je viens de tester la chose et j'obtiens le même résultat que toi sous Turbo Delphi ...

à mon avis c'est un Bug de Delphi ...
il faudrait peut être remonter l'info

 
@+
Cirec

<hr siz="" />
Commenter la réponse de Cirec
Messages postés
1105
Date d'inscription
dimanche 1 août 2004
Dernière intervention
17 août 2008
- 25 févr. 2008 à 19:26
0
Merci
Bon Ok, c'est donc pas une bourde que j'ai fait !!!

Voila donc tout ce que j'ai pu trouver pour pallier au problème (c'est pas super propre mais on fait comme on peut):

- déclarer un membre FLastShiftState: TShiftState dans la section private

- surcharger MouseDown et MouseMove par ça :

1. Pour MouseMove:

if (ssLeft in Shift) and not (ssLeft in FLastShiftState) then
MouseDown(mbLeft, FLastShiftState + [ssLeft], X, Y);
if (ssRight in Shift) and not (ssRight in FLastShiftState) then
MouseDown(mbLeft, FLastShiftState + [ssRight], X, Y);
if (ssMiddle in Shift) and not (ssMiddle in FLastShiftState) then
MouseDown(mbLeft, FLastShiftState + [ssMiddle], X, Y);
inherited;

2. Pour MouseDown:

FLastShiftState := Shift;
inherited;

Voila. C'étaient mes 2cts de bug de Delphi !
Commenter la réponse de florenth
Messages postés
1105
Date d'inscription
dimanche 1 août 2004
Dernière intervention
17 août 2008
- 25 févr. 2008 à 19:28
0
Merci
Zuuut ! c'est mbLeft, mbRight et mbMiddle et non pas mbLeft tout le temps !!!

D'ailleurs, comme on ne peut que double-cliquer avec le bouton gauche (il me semble) le problème ne devrait pas arriver avec les autres boutons, non ?
Commenter la réponse de florenth
Messages postés
1105
Date d'inscription
dimanche 1 août 2004
Dernière intervention
17 août 2008
- 25 févr. 2008 à 19:36
0
Merci
C'est encore moi !

Je viens de faire quelques autres tests, et aparament, le problème ne survient qu'avec les dialogues de Delphi.
Si on ferme une fiche en lui mettant Close dans le OnDblClick, la fiche d'en dessous ne reçoit aucun MouseMove, ni MouseDown, ce qui est l'effet normal.

Finalement, au lieu de recréer des évènements MouseDown, on ferait peut être mieux de supprimer les MouseMove qui n'ont rien à faire là.
Commenter la réponse de florenth
- 25 févr. 2008 à 20:18
0
Merci
Bon j'ai aussi l'erreur : l'evenement OnMouse est déclenché.
Commenter la réponse de Utilisateur anonyme
Messages postés
4580
Date d'inscription
samedi 19 janvier 2002
Dernière intervention
9 janvier 2013
- 25 févr. 2008 à 23:57
0
Merci
Je confirme et j'avoue que ça me laisse perplexe...

May Delphi be with you !
<hr color="#008000" />Pensez à cliquer sur Réponse acceptée lorsque la réponse vous convient.
Commenter la réponse de cs_Delphiprog
Messages postés
4304
Date d'inscription
samedi 16 octobre 2004
Dernière intervention
9 mars 2018
- 26 févr. 2008 à 04:14
0
Merci
Logique :

Quand tu es sur ta fiche (focused) elle recois les evenement MouseUp/Down  ... normal

Quand ta fiche PERD le focus elle perd egalement les evements MouseUp/Down ... normal

MAIS

Quand la fiche reprend le focus, alors qu'un doubleclick souris est en cours, la fiche receptionne le MouseUp ... puisque pendant le doubleclick sur un dialog (opendialog) voici ce qui se passe :

click bouton ouvrir = Affiche OpenDialog > click down ouvrir > click up ouvrir > click ok > Cache Opendialog > retour a la fiche principale.

doubleclik sur un fichier = Affiche OpenDialog > click down fichier > click up fichier > click down fichier > double click ok > ferme opendialog > retour a la fiche principal > click up anormal.

en fait cela viens du fait que le double click est validé dés le deuxieme down de curseur et non aprés le deuxieme up.
donc le deuxieme up intervient n'importe ou ... en gros il est perdus.
c'est plus un bug windows qu'un bug delphi.

le mieux serait de forcer l'ordre d'execution des 3 procedures :

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    ListBox1: TListBox;
    OpenDialog1: TOpenDialog;
    Button1: TButton;
    procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure Button1Click(Sender: TObject);
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure FormCreate(Sender: TObject);
  private
    FDmu : byte;
  protected
    function SafeDMUOrder(const Order: byte): boolean;
  public
    { Déclarations publiques }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

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

function TForm1.SafeDMUOrder(const Order: byte): boolean;
begin  Result :FDMU Order;
  if Result then
    FDMU := (FDMU+1) mod 3
end;

procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if SafeDMUOrder(0) then
    ListBox1.Items.Add('down');
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  if SafeDMUOrder(1) then
    ListBox1.Items.Add('move');
end;

procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if SafeDMUOrder(2) then
    ListBox1.Items.Add('up');
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  OpenDialog1.Execute;
end;

end.
 


Commenter la réponse de f0xi
Messages postés
1105
Date d'inscription
dimanche 1 août 2004
Dernière intervention
17 août 2008
- 26 févr. 2008 à 11:08
0
Merci
Tu mets le doigt dessus cher f0xi !

Mais tu oublies un détail dans ton test: les paramètres Button et Shift !!
Avec ta méthode, je me retrouve quand même avec un MouseMove et Shift = [ssLeft].

Donc, en m'inspirant de ton idée d'inhibiteur, j'ai rajouté le test des états des boutons, et voila ce que ça donne:

unit Unit1;

interface

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

const
CMouseDownLeft = 1;
CMouseUpLeft = 2;
CMouseMoveLeft = 4;

type
TForm1 = class(TForm)
Button1: TButton;
OpenDialog1: TOpenDialog;
ListBox1: TListBox;
procedure FormCreate(Sender: TObject);
procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure Button1Click(Sender: TObject);
private
// Les prochains évènements qu'on accepte
FAllowedMouseEvent: Byte;
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

function ButtonToStr(Button: TMouseButton): string;
begin
case Button of
mbLeft: Result := 'mbLeft';
mbRight: Result := 'mbRight';
mbMiddle: Result := 'mbMiddle';
end;
end;

function ShiftToStr(Shift: TShiftState): string;
begin
Result := '[ ';
if ssLeft in Shift then Result := Result + 'ssLeft ';
if ssRight in Shift then Result := Result + 'ssRight ';
if ssMiddle in Shift then Result := Result + 'ssMiddle ';
Result := Result + ']';
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
FAllowedMouseEvent := CMouseDownLeft;
end;

procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if (Button mbLeft) and (FAllowedMouseEvent and CMouseDownLeft 0) then
Exit;
FAllowedMouseEvent := CMouseUpLeft or CMouseMoveLeft;

ListBox1.Items.Insert(0, 'Down - Button = ' + ButtonToStr(Button)
+ ' - Shift = ' + ShiftToStr(Shift));
end;

procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if (Button mbLeft) and (FAllowedMouseEvent and CMouseUpLeft 0) then
Exit;
FAllowedMouseEvent := CMouseDownLeft;

ListBox1.Items.Insert(0, 'Up - Button = ' + ButtonToStr(Button)
+ ' - Shift = ' + ShiftToStr(Shift));
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
if (ssLeft in Shift) and (FAllowedMouseEvent and CMouseMoveLeft = 0) then
Exit;
// ne change pas les évents acceptés

ListBox1.Items.Insert(0, 'Move - Shift = ' + ShiftToStr(Shift));
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
OpenDialog1.Execute;
end;

end.



C'est déjà plus compliqué !
Et il reste un mini bug (mais faut vraiment y aller pour y arriver):
- ouvrir le opendialog
- enfoncer le bouton du milieu (et le laisser enfoncé)
- double-cliquer sur un fichier pour l'ouvrir (tout en gardant le bouton du milieu enfoncé)
- bouger la souris dans la form.

On obtient ainsi un "Move - Shift [ ssMiddle ]" puis un "Up - Button [ mbMiddle ]" sans avoir eu l'évènement Down correspondant (ce qui est logique, il a eu lieu ailleurs !)
Commenter la réponse de florenth
Messages postés
1105
Date d'inscription
dimanche 1 août 2004
Dernière intervention
17 août 2008
- 26 févr. 2008 à 11:11
0
Merci
De la même façon, si on appuie dans la fiche sur un bouton, et qu'on relache ailleurs de la fiche, elle ne reçoit pas le MouseUp.

C'est plutôt pas pratique !!!
Commenter la réponse de florenth

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.