florenth
Messages postés1023Date d'inscriptiondimanche 1 août 2004StatutMembreDernière intervention17 août 2008
-
25 févr. 2008 à 15:29
florenth
Messages postés1023Date d'inscriptiondimanche 1 août 2004StatutMembreDernière intervention17 août 2008
-
26 févr. 2008 à 11:11
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".
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
florenth
Messages postés1023Date d'inscriptiondimanche 1 août 2004StatutMembreDernière intervention17 août 20083 25 févr. 2008 à 18:08
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é.
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;
florenth
Messages postés1023Date d'inscriptiondimanche 1 août 2004StatutMembreDernière intervention17 août 20083 25 févr. 2008 à 19:26
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;
florenth
Messages postés1023Date d'inscriptiondimanche 1 août 2004StatutMembreDernière intervention17 août 20083 25 févr. 2008 à 19:36
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à.
f0xi
Messages postés4204Date d'inscriptionsamedi 16 octobre 2004StatutModérateurDernière intervention12 mars 202234 26 févr. 2008 à 04:14
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 :
florenth
Messages postés1023Date d'inscriptiondimanche 1 août 2004StatutMembreDernière intervention17 août 20083 26 févr. 2008 à 11:08
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:
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;
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;
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
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 !)