Une idée? pour la gestion de commandes à la souris

Partagez votre expérience de PureBasic avec les autres utilisateurs.
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Une idée? pour la gestion de commandes à la souris

Message par nico »

Certaines applications utilisent la souris pour passer des commandes, surtout employée sur les navigateur web comme firefox avec une extension.

Cela permet par exemple d'un click de souris suivi d'un déplacement de reculer ou d'avancer d'une page internet à l'autre.

J'ai pu trouver un code qui réalise cette intéressante possibilité mais avec une certaine complexité mettant en oeuvre un algorithme que mes pauvres moyens ne sauraient décripter. :lol:

Il m'est venu une idée de conception assez simple pour réaliser de telles commandes que je vous expose ici:

-Tout d'abord on serait limité à une figure géométrique simple limité au dessin de la forme d'un rectangle ce qui donnerait comme figure réalisable:
Déplacement de la souris de la gauche vers la droite
Déplacement de la souris de la droite vers la gauche
Déplacement de la souris de la gauche vers la droite puis vers le bas
Déplacement de la souris de la gauche vers la droite puis vers le haut
et ainsi de suite ...

Si on se limite à deux directions max, on obtient 12 figures possibles.

La réalisation serait celle-ci:
-je capture les mouvements de la souris, j'obtiens un certains nombre de points

-je compare le point suivant avec le précédent et je lui attribut une lettre suivant qu'il se trouve à gauche, à droite, en haut ou en bas du point qui le précède, soit les lettres g,d,h,b, je stocke le tout dans une chaine.

-donc pour un déplacement qui irait de gauche à droite puis vers le bas, je devrais avoir un résultat du genre:
"dddddddddddddddddddddddbbbbbbbbbbbbbbb"

Ensuite je réduis les doublons au nombre de 4 par exemple, ce qui me donne le résultat suivant:
"ddddbbbb"

Il me reste plus qu'à comparer cette chaine avec celles que j'aurais enregistrées pour voir si celle-ci corresponde à un mouvement autorisé qui donnerait lieu à une action.


Le premier avantage que je vois c'est qu'il ne serait absolument pas nécessaire de faire des angles droit lors d'un tracé, il serait donc très réactif.

Le désavantage c'est qu'on est très limité au niveau des figures qui se ressemblent plus ou moins et il reste difficile de leurs attribuer un sens logique à chacun d'eux au niveau de l'utilisateur.Toutefois je pense qu'en se limitant à 6 formes, cela reste déjà pas mal.

Le tout repose juste sur la conception d'un code qui permette de positionner un point par rapport à un autre.


Qu'est ce que vous pensez de tout cela?
C'est réalisable?
Cela ne fonctionnera jamais?
Vaut mieux laissé tomber?:lol:
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

...........
Dernière modification par Backup le dim. 02/oct./2011 13:15, modifié 1 fois.
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Message par nico »

Pour ma part, comparer un point à celui d'un point précédent serait plus simple à coder, je pense qu'en comparant juste x et y à l'autre point suffirait à connaitre mon déplacement.

Mais tout cela reste de la théorie!
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Message par nico »

Je viens de réaliser un code test et ça marche à merveille avec une mise en oeuvre très simpliste comme je le pensais. :)

Ce code n'est pas terminé, je ne détecte pas si une des touches de la souris est enfoncée pendant toute la durée du trajet, je ne réduit pas non plus les doublons pour permettre une comparaison.

Pour tester, faire d'abord un click gauche souris dans la fenêtre (pour réinitialiser la chaine) puis effectuer des mouvements de souris toujours dans la fenêtre et on voit dans le debugger la chaine décrivant le déplacement.

Code : Tout sélectionner

 Global mouvement.s
 
 Procedure MouseGesture(x.l,y.l,reset.l)
    Protected signeX.l,signeY.l
    Static xp.l,yp.l
    
    If reset
       xp=x
       yp=y
       mouvement=""
       Debug mouvement
      ProcedureReturn 1
    EndIf 
    
    signeX=0
    signeY=0
    
    Diff_x=x-xp
    Diff_y=y-yp

    If Diff_x<0 :Diff_x= -Diff_x:signeX=1:EndIf 
    If Diff_y<0 :Diff_y= -Diff_y:signeY=1:EndIf 
    
    If Diff_x >10 Or Diff_y >10
;         Debug Diff_x
;         Debug Diff_y
;         Debug signe
        
        If Diff_x >Diff_y
           If signeX
              mouvement=mouvement+"G"
           Else
              mouvement=mouvement+"D"
           EndIf 
        Else
           If signeY
              mouvement=mouvement+"H"
           Else
              mouvement=mouvement+"B"
           EndIf 
        EndIf 
        xp=x
        yp=y
        Debug mouvement
    EndIf 

    ProcedureReturn 1
 EndProcedure 
 
 
  Procedure WinCallback(hWnd, Msg, wParam, lParam) 

    Select Msg
        Case #WM_MOUSEMOVE
            x=lparam & $FFFF
            y=lparam>>16
            ;Debug "x="+Str(x)+"      "+"y="+Str(y)
            MouseGesture(x,y,0)
            
         Case #WM_LBUTTONDOWN
            x=lparam & $FFFF
            y=lparam>>16
            MouseGesture(x,y,1)
    EndSelect 
  
    ProcedureReturn #PB_ProcessPureBasicEvents 
  EndProcedure


If OpenWindow(0, 100, 200, 600, 600, "PureBasic Window", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
  SetWindowCallback(@WinCallback()) 

  Repeat
    EventID = WaitWindowEvent()

    Select  EventID 
        Case #PB_Event_CloseWindow
          Quit = 1
    EndSelect 

  Until Quit = 1
  
EndIf
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

pas mal !! :)
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

ça peut m'intéresser aussi ce truc là , merci :)
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Message par nico »

J'ai fini par faire un exemple complet:
Telecharger d'abord l'image ici:trace.png, puis l'enregistrer sous "c:\trace.png"

Ensuite vous pouvez essayer les différentes figures proposées (28 au total pour 3 segments max)

Pour commencer un tracé, click gauche du bouton de la souris enfoncé et maintenu pendant la durée du tracé puis on relache, le trace doit se faire dans la zone cliente de la fenêtre.

Le code:

Code : Tout sélectionner

 UsePNGImageDecoder()

 Global HookMouse.l,mouvement.s
 
 Procedure Compare(Chaine_Decripte.s)
    Select Len(Chaine_Decripte)
        Case 4
            Select Chaine_Decripte
                Case "GGGG":MessageRequester("Find"," Trace N°1")
                Case "DDDD":MessageRequester("Find"," Trace N°2")
                Case "HHHH":MessageRequester("Find"," Trace N°3")
                Case "BBBB":MessageRequester("Find"," Trace N°4")
            EndSelect 
               
        Case 8
            Select Chaine_Decripte
                Case "HHHHGGGG":MessageRequester("Find"," Trace N°5")
                Case "HHHHDDDD":MessageRequester("Find"," Trace N°6")
                Case "BBBBGGGG":MessageRequester("Find"," Trace N°7")
                Case "BBBBDDDD":MessageRequester("Find"," Trace N°8")
                Case "DDDDHHHH":MessageRequester("Find"," Trace N°9")
                Case "GGGGHHHH":MessageRequester("Find"," Trace N°10")
                Case "DDDDBBBB":MessageRequester("Find"," Trace N°11")
                Case "GGGGBBBB":MessageRequester("Find"," Trace N°12")
            EndSelect 
            
        Case 12
            Select Chaine_Decripte
                Case "DDDDBBBBGGGG":MessageRequester("Find"," Trace N°13")
                Case "BBBBGGGGHHHH":MessageRequester("Find"," Trace N°14")
                Case "GGGGHHHHDDDD":MessageRequester("Find"," Trace N°15")
                Case "HHHHDDDDBBBB":MessageRequester("Find"," Trace N°16")
                Case "DDDDHHHHGGGG":MessageRequester("Find"," Trace N°17")
                Case "BBBBDDDDHHHH":MessageRequester("Find"," Trace N°18")
                Case "GGGGBBBBDDDD":MessageRequester("Find"," Trace N°19")
                Case "HHHHGGGGBBBB":MessageRequester("Find"," Trace N°20")

                Case "DDDDHHHHDDDD":MessageRequester("Find"," Trace N°21")
                Case "GGGGBBBBGGGG":MessageRequester("Find"," Trace N°22")
                Case "DDDDBBBBDDDD":MessageRequester("Find"," Trace N°23")
                Case "GGGGHHHHGGGG":MessageRequester("Find"," Trace N°24")
                Case "HHHHDDDDHHHH":MessageRequester("Find"," Trace N°25")
                Case "BBBBGGGGBBBB":MessageRequester("Find"," Trace N°26")
                Case "HHHHGGGGHHHH":MessageRequester("Find"," Trace N°27")
                Case "BBBBDDDDBBBB":MessageRequester("Find"," Trace N°28")
            
            EndSelect 
    EndSelect    
 EndProcedure
 
 Procedure Decript()
    Protected Doublon.l,Caractere.s,Caractere_precedent.s
    Protected Chaine_Decripte.s
    
    Doublon=0
    Chaine_Decripte=""
    Caractere_precedent=""
    
    If Len(mouvement)>3
      For a=1 To Len(mouvement)
        Caractere.s=Mid(mouvement, a, 1)
        
        If Caractere_precedent=Caractere
          Doublon=Doublon+1
        Else
          Doublon=0
        EndIf
  
        If Doublon<4
          Chaine_Decripte=Chaine_Decripte+Caractere
        EndIf 
      
        Caractere_precedent=Caractere
      Next a
      
      Debug Chaine_Decripte
    
      Compare(Chaine_Decripte)
    EndIf 
 EndProcedure
 
 
 Procedure MouseGesture(x.l,y.l,reset.l)
    Protected signeX.l,signeY.l,Diff_x.l,Diff_y.l
    Static xp.l,yp.l
    
    If reset
       xp=x
       yp=y
       mouvement=""
      ProcedureReturn 1
    EndIf
   
    signeX=0 : signeY=0
   
    Diff_x=x-xp : Diff_y=y-yp

    If Diff_x<0 :Diff_x= -Diff_x:signeX=1:EndIf
    If Diff_y<0 :Diff_y= -Diff_y:signeY=1:EndIf
   
    If Diff_x >10 Or Diff_y >10
;         Debug Diff_x
;         Debug Diff_y
;         Debug signe
       
        If Diff_x >Diff_y
           If signeX
              mouvement=mouvement+"G"
           Else
              mouvement=mouvement+"D"
           EndIf
        Else
           If signeY
              mouvement=mouvement+"H"
           Else
              mouvement=mouvement+"B"
           EndIf
        EndIf
        xp=x
        yp=y
    EndIf

    ProcedureReturn 1
 EndProcedure
 
 

ProcedureDLL HookMouse(nCode, wParam, lParam)
  Static Start.l

  If nCode < 0
    ProcedureReturn CallNextHookEx_(HookMouse, nCode, wParam, lParam)
  EndIf
  
   *MOUSESTRUCT.MOUSEHOOKSTRUCT = lParam
   *position.POINT=*MOUSESTRUCT\pt

   Select wParam
        Case #WM_MOUSEMOVE
            If Start
              MouseGesture(*position\x,*position\y,0)
            EndIf 
            
         Case #WM_LBUTTONDOWN
            Start=1
            MouseGesture(*position\x,*position\y,1)
            
         Case #WM_LBUTTONUP
            Start=0
            Decript()
   EndSelect
   
   ProcedureReturn CallNextHookEx_(HookMouse, nCode, wParam, lParam)
EndProcedure 


LoadImage(0,"c:\trace.png")

If OpenWindow(0, 100, 200, 600, 600, "PureBasic Window", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
  lpdwProcessId = GetWindowThreadProcessId_(WindowID(0), @processus) 
  HookMouse=SetWindowsHookEx_(#WH_MOUSE   , @HookMouse(), 0, lpdwProcessId) 
  
  CreateGadgetList(WindowID(0))
  ImageGadget(0,0,0,600,600,ImageID(0))
  
  Repeat
    EventID = WaitWindowEvent()

    Select  EventID
        Case #PB_Event_CloseWindow
          Quit = 1
    EndSelect

  Until Quit = 1
UnhookWindowsHookEx_(HookMouse) 
EndIf
Avatar de l’utilisateur
venom
Messages : 3137
Inscription : jeu. 29/juil./2004 16:33
Localisation : Klyntar
Contact :

Message par venom »

:P et bien nico chez moi sa fonctionne parfaitement Bravo :wink: .



@++
Windows 10 x64, PureBasic 5.73 x86 & x64
GPU : radeon HD6370M, CPU : p6200 2.13Ghz
Répondre