Novembre 2024 | Lun | Mar | Mer | Jeu | Ven | Sam | Dim |
---|
| | | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | | Calendrier |
|
|
| BUG avec MOUSE_X_POSITION et MOUSE_Y_POSITION | |
| | Auteur | Message |
---|
Klaus
Nombre de messages : 12331 Age : 75 Localisation : Ile de France Date d'inscription : 29/12/2009
| Sujet: BUG avec MOUSE_X_POSITION et MOUSE_Y_POSITION Lun 6 Aoû 2012 - 12:58 | |
| Cette fois, j'ai l'impression d'être vraiment tombé sur un bug. Quelques soient mes essais, les valeurs retournées ne correspondent pas à la réalité. J'ai déjà signalé que les objets (en particulier les PICTURE puisque je travaille dessus) semblent mémoriser le point de sortie du curseur, et ces fonctions retournent systématiquement ces valeurs, même si le curseur a déjà quitté l'objet. Conséquence: impossible de savoir où se trouve le curseur réellement. Ceci pourrait être considéré comme un fonctionnement à accepter. Mais il y a pire. Si j'ai deux picture aux MEMES oordonnées et de MEME dimension, dont un est caché par HIDE. Je clique sur le picture visible - j'ai bien les coordonnées par MOUSE_X_POSITION et MOUSE_Y_POSITION. Attention: je ne veux PAS utiliser MOUSE_X_LEFT_DOWN et MOUSE_Y_LEFT_DOWN dans mon projet ! Donc, je clique, j'ai mes positions, puis je cache le picture par HIDE et affiche son double par SHOW. Mêmes dimensions, même endroit. Le curseur est donc automatiquement au-dessus de ce second picture, aux mêmes coordonnées ! Que nenni: MOUSE_X_POSITION et MOUSE_Y_POSITION me donnent (0,0) la première fois, et dans des échéances suvantes, ces fonctions me donnent les coordonnées de sortie de l'objet par rapport à la tentative précédente. Dans certains cas, il suffit d'insérer un DISPLAY à un endroit stratégique pour que ça marche, mais pas dans d'autres. Dans certains cas, la position n'est actualisée et correcte qu'après un ou deux clics gauches dans le second picture. Avant, les valeurs retournées sont fantaisistes. Voici un programme qui met cela en évidence: - Code:
-
label tst, sel, aff dim x1%, x2%, y1%, y2% dim test%, s$
picture 1 : top 1,10 : left 1,10 : color 1,255,0,0 picture 2 : top 2,10 : left 2,10 : color 2,0,255,0 : hide 2 image 3 combo 10 : top 10,200 : left 10,10 : width 10,300 : on_click 10,sel item_add 10,"Test de base ==> erreur" item_add 10,"avec DISPLAY ==> ok" item_add 10,"en remplaçant le picture 2 ==> erreur" item_add 10,"en remplaçant le picture 2 avec display ==> erreur" item_add 10,"en dessinant dans le picture 2 ==> erreur" item_add 10,"en dessinant dans le picture 2 avec display==> ok" alpha 20 : top 20,250 : left 20,10 : font_size 20,12 s$ = "Choisir un test, puis cliquer sur l'image."+chr$(13)+chr$(10) s$ = s$ + "Le premier clic remplace l'image et affiche les coordonnées."+chr$(13)+chr$(10) s$ = s$ + "Les deux paires de coordonnées devraient être identiques."+chr$(13)+chr$(10) s$ = s$ + "Puis continuez à cliquer..." caption 20,s$
on_click 1,tst on_click 2,aff
test% = 0
end
sel: test% = item_index(10) - 1 show 1 : hide 2 return
tst: select test% case 0: ' test de base ==> erreur show 2 : hide 1 case 1: ' avec DISPLAY ==> ok show 2 : hide 1 display case 2: ' en remplaçant le picture 2 ==> erreur 2d_target_is 1 : 2d_image_copy 3,0,0,width(1)-1,height(1)-1 2d_target_is 2 : 2d_image_paste 3,0,0 show 2 : hide 1 case 3: ' en remplaçant le picture 2 avec display ==> erreur 2d_target_is 1 : 2d_image_copy 3,0,0,width(1)-1,height(1)-1 2d_target_is 2 : 2d_image_paste 3,0,0 show 2 : hide 1 display case 4: ' en dessinant dans le picture 2 ==> erreur 2d_target_is 2 show 2 : hide 1 2d_circle 50,50,30 case 5: ' en dessinant dans le picture 2 avec display==> ok 2d_target_is 2 2d_circle 50,50,30 show 2 : hide 1 display end_select aff: x1% = mouse_x_position(1) y1% = mouse_y_position(1) x2% = mouse_x_position(2) y2% = mouse_y_position(2) caption 0,str$(x1%)+" "+str$(y1%)+" / " + str$(x2%)+" "+str$(y2%) return | |
| | | Jicehel
Nombre de messages : 5947 Age : 52 Localisation : 77500 Date d'inscription : 18/04/2011
| Sujet: Re: BUG avec MOUSE_X_POSITION et MOUSE_Y_POSITION Lun 6 Aoû 2012 - 19:27 | |
| En effet, le premier clic après changement modifie les valeurs qu'il ne devrait pas, mais pas les clics suivants. On doit pouvoir parrer ce comportement anormal par programmation, mais en effet, c'est un comportement anormal | |
| | | Klaus
Nombre de messages : 12331 Age : 75 Localisation : Ile de France Date d'inscription : 29/12/2009
| Sujet: Re: BUG avec MOUSE_X_POSITION et MOUSE_Y_POSITION Mar 7 Aoû 2012 - 0:33 | |
| Voici un autre code mettant ce problème en évidence. Il y a 3 objets et un bouton. Un clic sur le bouton place le résultat de MOUSE_X_POSITION et MOUSE_Y_POSITION de la form 0 et de chacun de ces objets dans le mémo (objet 3). Si l'on clique directement sur ce bouton Démarrer, on obtient (0,0) pour les 3 objets, et l'adresse de sortie de la form 0 là où le curseur est entré dans le bouton. Maintenant, on fait glisser le curseur sur l'un ou l'autre des objets, avant de recliquer sur le bouton: l'adresse de sortie de l'objet reste mémorisée, alors même que le curseur a quitté l'objet (forcément, puisqu'il est sur le bouton !). Et si l'on passe sur les 3 objets, le résultat est le même: on a l'adresse de sortie pour chacun de ces objets, et non la position réelle du curseur. Alors, où est réellement le curseur ? Dans aucun de ces 3 objets, puisqu'il est sur le bouton ! Et c'est bien là le problème. - Code:
-
label go dim s$
edit 1 : top 1,10 : left 1,10 picture 2 : top 2,40 : left 2,10 memo 3 : top 3,40 : left 3,300 button 10 : top 10,180 : left 10,10 : caption 10,"Démarrer" on_click 10,go s$ = "Cliquez sur Démarrer."+chr$(13)+chr$(10) s$ = s$ + "Puis, passez le curseur dans un des champs, puis cliquez à nouveau."+chr$(13)+chr$(10) s$ = s$ + "Puis, faites de même avec les autres champs."+chr$(13)+chr$(10) s$ = s$ + "Constat: les points de sortie de chaque objet restent mémorisés !" message s$ end
go: clear 3 item_add 3,"0: "+str$(mouse_x_position(0))+","+str$(mouse_y_position(0)) item_add 3,"1: "+str$(mouse_x_position(1))+","+str$(mouse_y_position(1)) item_add 3,"2: "+str$(mouse_x_position(2))+","+str$(mouse_y_position(2)) item_add 3,"3: "+str$(mouse_x_position(3))+","+str$(mouse_y_position(3)) return
EDIT C'est à se demander s'il ne convient pas de remédier à cela par une DLL avec des fonctions donnant l'adresse du curseur dans la form active et/ou physiquement dans l'écran. Ce ne serait pas un problème. Et ayant les coordonnées dans la form active, on peut en déduire l'objet concerné, en comparant les coordonnées des objets avec celles du curseur, sachant (du moins dans mes programmes où les objets sont créés par numéros croissants) qu'en cas de recouvrement de plusieurs objets, c'est celui avec le numéro d'objet le plus grand qui est le bon. Mais ce serait dommage de monter une telle usine à gaz pour une info aussi simple. Si les fonctions MOUSE_X_POSITION et MOUSE_Y_POSITION retournaient -1 en cas d'absence du curseur dans l'objet, ou mieux: si une variable système NUMBER_OBJECT_MOUSE donnait le numéro d'objet contenant la souris, quel progrès... | |
| | | Yannick
Nombre de messages : 8635 Age : 53 Localisation : Bretagne Date d'inscription : 15/02/2010
| Sujet: re Mar 7 Aoû 2012 - 1:05 | |
| c'est ce que je proposais mais je l'ai mal formulé lors de ta demande . Je me disais que le relevé de position de la souris devrait plutôt se faire sur la "form N" que sur "objet N" car les objets ont tous une position de départ connue qu'on les place dès le départ ( top N,y% / left N,x% ) ou non (top N,0 / left N,0)... en fait : mouse_x_position(N) == position en x de la souris sur le form de n° N et son pendant pour y Edit : je viens de regarder en freebasic ( langage de la dll de nardo26, je pense ) la position de la souris est récupérée depuis l'écran mais je n'y est pas vu la possibilité de la récupérer depuis un form.Edit 2: si tu pars sur une dll qui récupère les coordonnées de la souris sur le form ,et que tu veux que seul le cadre de travail de la fenêtre soit concerné, tu vas te heurté au différentes versions de Windows et autres qui ont des marge différentes ( cf: les posts sur histo.dll).
Dernière édition par ygeronimi le Mar 7 Aoû 2012 - 1:24, édité 1 fois | |
| | | Klaus
Nombre de messages : 12331 Age : 75 Localisation : Ile de France Date d'inscription : 29/12/2009
| Sujet: Re: BUG avec MOUSE_X_POSITION et MOUSE_Y_POSITION Mar 7 Aoû 2012 - 1:22 | |
| Pas tout à fait, Ygeronimi. Et c'est bien le problème. Tant que le curseur est sur la form 0 sans toucher aucun objet, ces fonctions retournent la bonne valeur en passant 0 comme paramètre. Mais dès que le curseur entre dans un objet, la form 0 CESSE de traquer le curseur et l'objet touché prend la relève. Mais les coordonnées du dernier pixel de la form 0 touché juste avant d'entrer dans l'objet restent actives et continuent à être renvoyées par ces fonctions ! J'ai regardé ce qu'on peut faire en Delphi, et c'est extrêmement simple ! on récupère les coordonnées logiques du curseur par rapport à la form active de la manière suivante: - Code:
-
function MOUSE_X_POSITION:integer; stdcall; export; var pt: TPoint; begin GetCursorPos(pt) ; pt := ScreenToClient(pt); result := pt.X; end;
et de façon similaire pour la coordonnée Y. Un moyen simple de savoir si le curseur est dans un objet (simplement pompé du net - merci Google): - Code:
-
procedure IsMouseInControl(MyControl: TObject); var MyPoint : TPoint; begin MyPoint = MyControl.ScreenToClient(Mouse.CursorPos); if (PtInRect(MyControl.ClientRect, MyPoint) then begin // Mouse is inside the control, do something here end; end;
Je pense ce problème existe simplement parce que Jack n'a pas eu à traiter ce genre de cas, car une solution aussi simple que cela n'a pas pu échapper à Jack. | |
| | | Yannick
Nombre de messages : 8635 Age : 53 Localisation : Bretagne Date d'inscription : 15/02/2010
| Sujet: re Mar 7 Aoû 2012 - 1:27 | |
| | |
| | | Klaus
Nombre de messages : 12331 Age : 75 Localisation : Ile de France Date d'inscription : 29/12/2009
| Sujet: Re: BUG avec MOUSE_X_POSITION et MOUSE_Y_POSITION Mar 7 Aoû 2012 - 1:34 | |
| Les fonctions ScreenToClient, ClientToScreen, GetCursorPos ainsi que la propriété ClientRect sont justement faites pour ça. Elles fonctionnent de façon transparente pour les différentes versions de Windows. EDIT Petit programme de démo en Delphi. On place un Edit, un Picture, un Memo et un Button sur la form, et voici Unit1.pas: - Code:
-
unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, jpeg, ExtCtrls;
type TForm1 = class(TForm) Edit1: TEdit; Image1: TImage; Memo1: TMemo; Button1: TButton; procedure Button1Click(Sender: TObject); private { Déclarations privées } public { Déclarations publiques } end;
var Form1: TForm1;
implementation
{$R *.dfm}
function IsMouseOverControl(const ctrl: TControl): boolean; var sr : TRect; begin sr := Rect(ctrl.ClientToScreen(Point(0, 0)), ctrl.ClientToScreen(Point(ctrl.Width, ctrl.Height)));
result := PtInRect(sr, Mouse.CursorPos); end;
procedure TForm1.Button1Click(Sender: TObject); var pt: TPoint; begin pt := ClientToScreen(point(memo1.Left+25, memo1.Top+35)) ; SetCursorPos(pt.x, pt.y) ; GetCursorPos(pt) ; pt := ScreenToClient(pt); if IsMouseOverControl(Edit1) then showmessage('Dans EDIT1 '+inttostr(pt.X)+','+inttostr(pt.Y)); if IsMouseOverControl(Image1) then showmessage('Dans IMAGE1 '+inttostr(pt.X)+','+inttostr(pt.Y)); if IsMouseOverControl(Memo1) then showmessage('Dans MEMO1 '+inttostr(pt.X)+','+inttostr(pt.Y)); end;
end.
On peut balader le curseur sur tous les objets, puis cliquer sur le bouton. Ceci force le curseur dans le mémo, puis teste les coordonnées du curseur dans les 3 objets. Et bien que le curseur ait pénétré dans les 3 objets, il n'y a pas de coordonnées pour l'Edit ni pour le Picture, mais seulement pour le Mémo qu contient le vrai curseur, contrairement à Panoramic qui donne des coordonnées pour chaque objet. | |
| | | Yannick
Nombre de messages : 8635 Age : 53 Localisation : Bretagne Date d'inscription : 15/02/2010
| Sujet: re Mar 7 Aoû 2012 - 2:18 | |
| | |
| | | Klaus
Nombre de messages : 12331 Age : 75 Localisation : Ile de France Date d'inscription : 29/12/2009
| Sujet: Re: BUG avec MOUSE_X_POSITION et MOUSE_Y_POSITION Mar 7 Aoû 2012 - 15:22 | |
| J'ai réalisé les fonctions nécessaires dans une DLL en Delphi. C'était finalement vraiment simple. Je les ai intégrées dans MouseOperations.dll et j'ai mis la doc à jour (dans mon WebDav). Voici, extrait de la doc, la description des 3 nouvelles fonctions: - Code:
-
Récupérer la position de la souris à l’intérieur d’une form i%=dll_call3("GetMousePosition",hnd%,adr(x%),adr(y%)) retourne la position de la souris en coordonnées de la form en pixels hnd% est le handle de la form concernée
Récupérer la position de la souris en coordonnées absolues de l’écran i%=dll_call2("GetAbsoluteMousePosition",adr(x%),adr(y%)) retourne la position de la souris en coordonnées de l'écran en pixels
Tester si un point est à l’intérieur d’un rectangle i%=dll_call6("IsPointInRectangle",xp%,yp%,xr%,yr%,wr%,hr%) retourne 1 si le point est dans le rectangle, et 0 sinon le rectangle est défini par le point en haut à gauche (xr%,yr%) ainsi que la largeur wr% et la hauteur hr%
Et voici les 3 petits programmes de démo qui vont avec: test_GetMousePosition.bas: - Code:
-
' test_GetMousePosition.bas
label tick
dim i%, x%, y%, hnd%
top 0,100 : left 0,200 : hnd% = handle(0)
dll_on "MouseOperations.dll"
picture 10 : top 10,30 : left 10,20 color 10,255,0,0
timer 1 : timer_interval 1,100 : on_timer 1,tick
end
tick: timer_off 1 i% = dll_call3("GetMousePosition",hnd%,adr(x%),adr(y%)) caption 0,str$(x%)+","+str$(y%) timer_on 1 return
test_GetAbsoluteMousePosition.bas: - Code:
-
' test_GetAbsoluteMousePosition.bas
label tick
dim i%, x%, y%, hnd%
top 0,100 : left 0,200 : hnd% = handle(0)
dll_on "MouseOperations.dll"
picture 10 : top 10,30 : left 10,20 color 10,255,0,0
timer 1 : timer_interval 1,100 : on_timer 1,tick
end
tick: timer_off 1 i% = dll_call2("GetAbsoluteMousePosition",adr(x%),adr(y%)) caption 0,str$(x%)+","+str$(y%) timer_on 1 return
test_IsPointInRectangle.bas: - Code:
-
' test_IsPointInRectangle.bas
label tick
dim i%, x%, y%, hnd%, no%, xr%, yr%, wr%, hr%, s$ hnd% = handle(0)
picture 1 : top 1,10 : left 1,10 : color 1,255,0,0 picture 2 : top 2,40 : left 2,40 : color 2,0,255,0 picture 3 : top 3,70 : left 3,70 : color 3,0,0,255
dll_on "MouseOperations.dll"
s$ = "Laissez le curseur glisser sur l'écran."+str$(13)+str$(10) s$ = s$ + "La caption de la form donne l'objet survolé." message s$
timer 10 : timer_interval 10,100 : on_timer 10,tick end
tick: timer_off 10 i% = dll_call3("GetMousePosition",hnd%,adr(x%),adr(y%)) if x%=-1 caption 0,"Le curseur est en-dehors de la form 0." else for no%=3 to 0 step -1 xr% = left(no%) yr% = top(no%) wr% = width(no%) hr% = height(no%) i% = dll_call6("IsPointInRectangle",x%,y%,xr%,yr%,wr%,hr%) if i%>0 caption 0,"Le curseur est dans l'objet "+str$(no%) exit_for end_if next no% end_if timer_on 10 return
Plus aucun problème pour savoir où se trouve le curseur, pour identifier l'objet sous le curseur, etc ! Et pour ceux que cela intéresse, voici un extrait de la DLL avec les sources ce ces fonctions: - Code:
-
Type PInteger = ^Integer;
// return the logical mouse position Function GetMousePosition(hnd: integer; x,y:Pinteger):integer; stdcall; export; var pt: TPoint; rect: TRect; begin GetCursorPos(pt) ; Windows.GetClientRect(hnd,rect); ScreenToClient(hnd,pt); if PtInRect(rect, pt) then begin x^:= pt.X; y^:= pt.Y; end else begin x^:= -1; y^:= -1; end; result := 0; end;
// return the physical mouse position Function GetAbsoluteMousePosition(x,y:Pinteger):integer; stdcall; export; var pt: TPoint; begin GetCursorPos(pt) ; x^:= pt.X; y^:= pt.Y; result := 0; end;
// check if a point is in a rectangle Function IsPointInRectangle(xp,yp,xr,yr,wr,hr:integer):integer; stdcall; export; var pt: TPoint; rect: TRect; begin pt.X := xp; pt.Y := yp; rect.Left := xr; rect.Top := yr; rect.Right := xr + wr - 1; rect.Bottom := yr + hr - 1; if PtInRect(rect, pt) then result := 1 else result := 0; end;
Maintenant, je vais appliquer cela à mon jeu Puzzle. Mais ce serait vraiment sympa de trouver ces fonctionnalités de façon native dans Panoramic ! Utiliser une DLL pour un petit jeu, j'aurais voulu l'éviter... | |
| | | Yannick
Nombre de messages : 8635 Age : 53 Localisation : Bretagne Date d'inscription : 15/02/2010
| Sujet: re Mar 7 Aoû 2012 - 18:58 | |
| Bravo Klaus !,
Trois fonctions très pratiques qui vont être très utiles... | |
| | | Contenu sponsorisé
| Sujet: Re: BUG avec MOUSE_X_POSITION et MOUSE_Y_POSITION | |
| |
| | | | BUG avec MOUSE_X_POSITION et MOUSE_Y_POSITION | |
|
Sujets similaires | |
|
| Permission de ce forum: | Vous ne pouvez pas répondre aux sujets dans ce forum
| |
| |
| |