Mouse Cursor "Capture".

Aide et conseils concernant AutoIt et ses outils.
Règles du forum
.
Répondre
Avatar du membre
Barthandelus
Niveau 3
Niveau 3
Messages : 46
Enregistré le : mer. 02 janv. 2019 14:34
Status : Hors ligne

Mouse Cursor "Capture".

#1

Message par Barthandelus » mar. 15 oct. 2019 09:33

Bonjour,

Je suis actuellement en train de développer un petit script pour mes besoins personnels : Chrome Remote Desktop, la WebApp de Google, permet de prendre la main sur ses ordinateurs distants. Je trouve cet outil très stable en terme de réponse et de rapidité (en tout cas, pour mon usage). Hors voilà - Il m'arrive parfois de jouer à des jeux directement via ce système.

Cependant, et là est ma problématique, à l'inverse de Stadia, Chrome Remote Desktop ne capture pas la souris comme le ferait n'importe quelle application OpenGL. Le soucis étant que le capture de la souris se fait sur l'ordinateur, mais pas à distance. Pour combler ce soucis et faire de Chrome Remote Desktop un "Stadia Gratuit" (le terme n'est pas vraiment adapté, étant donné que Stadia est un one-buy-time, que je possède déjà, j'attends sa sortie avec impatience. /o/).

J'ai donc pondu le script suivant en me basant sur l'exemple de HotKeySet() :

Global $g_bPaused = False, $g_bStop = False
Global $MouseX = 0
Global $MouseY = 0
Global $CaptureFocus = False

HotKeySet("{ESC}", "HotKeyPressed")
HotKeySet("^{Enter}", "HotKeyPressed")
HotKeySet("^{q}", "HotKeyPressed")

While Not $g_bStop
    Sleep(25)
        If($CaptureFocus) Then
                MouseMove($MouseX, $MouseY, 0)
        EndIf
WEnd

Func HotKeyPressed()
    Switch @HotKeyPressed
        Case "{ESC}"
                ; Pause du programme
                $CaptureFocus = False
        Case "^{Enter}"
                ; Action à faire.
                Local $aPosition = MouseGetPos()
                $MouseX = $aPosition[0]
                $MouseY = $aPosition[1]
                $CaptureFocus = True
        Case "^{q}" ; Fermer le programme
                $g_bStop = True
    EndSwitch
EndFunc

ça fonctionne sur le principe, malheureusement l'usage de MouseMove(), même en speed 0, considère bien qu'il s'agit d'un déplacement. Le soucis, c'est donc que dans une application 3D, la caméra est bougé par le mouvement de la souris avant d'être réinitialisé après le Sleep(). Existerait-il une autre fonction, ou une option, qui permettrait de réinitialiser le curseur à sa position initiale, sans pour autant provoquer un mouvement ?

EDIT : Pour des soucis de sécurité, la liste des shortcuts du programme :
- CTRL + ENTER : Démarrer le freez de la souris.
- ESC : Arrêter le freez de la souris.
- CTRL+Q : Fermeture du programme (Arrête le freez de la souris s'il est en cours).

Avatar du membre
mikell
Modérateur
Modérateur
Messages : 5887
Enregistré le : dim. 29 mai 2011 16:32
Localisation : Deep Cévennes
Status : Hors ligne

Re: Mouse Cursor "Capture".

#2

Message par mikell » mar. 15 oct. 2019 21:01

Au hasard, peut-être essayer d'utiliser un hook + une hotkey pour intercepter le message souris avant qu'il soit transmis à la camera ?
#include <WinAPI.au3>
#include <WindowsConstants.au3>
#include <Misc.au3>

Global $hHook
Local $hFunc, $pFunc, $hMod
HotKeySet('{ESC}', '_Close')

$hFunc = DllCallbackRegister('_MouseProc', 'lresult', 'int;int;int')
$pFunc = DllCallbackGetPtr($hFunc)
$hMod = _WinAPI_GetModuleHandle(0)
$hHook = _WinAPI_SetWindowsHookEx($WH_MOUSE_LL, $pFunc, $hMod)

While 1
    Sleep(20)
WEnd


Func _MouseProc($iCode, $iwParam, $ilParam)
    If $iCode < 0 Then Return _WinAPI_CallNextHookEx($hHook, $iCode, $iwParam, $ilParam)
    Switch $iwParam
          Case $WM_MOUSEMOVE
             $pos = MouseGetPos()
                 If _IsPressed("11") Then  ; CTRL
                    Return Tooltip($pos[0] & " x " & $pos[1], 0, 0)
                 EndIf
    EndSwitch
    Return _WinAPI_CallNextHookEx($hHook, $iCode, $iwParam, $ilParam)
EndFunc   ;==>_MouseProc

Func _Close()
    _WinAPI_UnhookWindowsHookEx($hHook)
    DllCallbackFree($hHook)
    Exit
EndFunc   ;==>_Close
" L'échec est le fondement de la réussite. " (Lao-Tseu )
" Plus ça rate, plus on a de chances que ça marche " (les Shadoks )

Avatar du membre
Barthandelus
Niveau 3
Niveau 3
Messages : 46
Enregistré le : mer. 02 janv. 2019 14:34
Status : Hors ligne

Re: Mouse Cursor "Capture".

#3

Message par Barthandelus » mer. 16 oct. 2019 08:11

Hello,

ça ne semble pas fonctionner, mais c'est peut être moi qui n'agit pas de la bonne façon. J'ai modifié ton code pour l'adapter à mon objectif :

#include <WinAPI.au3>
#include <WindowsConstants.au3>
#include <Misc.au3>

Global $hHook, $MouseX = 0, $MouseY = 0
Local $hFunc, $pFunc, $hMod
HotKeySet('{ESC}', '_Close')

$hFunc = DllCallbackRegister('_MouseProc', 'lresult', 'int;int;int')
$pFunc = DllCallbackGetPtr($hFunc)
$hMod = _WinAPI_GetModuleHandle(0)
$hHook = _WinAPI_SetWindowsHookEx($WH_MOUSE_LL, $pFunc, $hMod)

While 1
    Sleep(20)
WEnd

Func _MouseProc($iCode, $iwParam, $ilParam)
    If $iCode < 0 Then Return _WinAPI_CallNextHookEx($hHook, $iCode, $iwParam, $ilParam)
                Switch $iwParam
                        Case $WM_MOUSEMOVE
                                If _IsPressed("11") Then  ; CTRL
                                        MouseMove($MouseX, $MouseY, 0)
                                Else
                                        $pos = MouseGetPos()
                                        $MouseX = $pos[0]
                                        $MouseY = $pos[1]
                                EndIf
                EndSwitch
    Return _WinAPI_CallNextHookEx($hHook, $iCode, $iwParam, $ilParam)
EndFunc   ;==>_MouseProc

Func _Close()
    _WinAPI_UnhookWindowsHookEx($hHook)
    DllCallbackFree($hHook)
    Exit
EndFunc   ;==>_Close

Actuellement, avec ce code, le freez de la souris ne se fait tout simplement plus. Le curseur est bien téléporté au point de départ en maintenant la touche CTRL appuyée, mais la souris continue de se balader librement, ce qui ne permet pas de faire le suivi de la caméra.

Avatar du membre
mikell
Modérateur
Modérateur
Messages : 5887
Enregistré le : dim. 29 mai 2011 16:32
Localisation : Deep Cévennes
Status : Hors ligne

Re: Mouse Cursor "Capture".

#4

Message par mikell » mer. 16 oct. 2019 13:11

L'idée c'était de jouer sur le rôle de Return dans MouseProc pour essayer d'intercepter le message, par exemple
 If _IsPressed("11") Then
         Return 1
 EndIf
dans ce cas le message est complètement bloqué
Dans mon exemple, ça affiche le Tooltip. Tooltip retourne 1 donc théoriquement ça devrait s'arrêter là...
Vu que je ne connais pas le contexte (et que je ne comprends pas bien ce que veut dire "freez de la souris") je sais plus trop quoi ajouter :mrgreen:
" L'échec est le fondement de la réussite. " (Lao-Tseu )
" Plus ça rate, plus on a de chances que ça marche " (les Shadoks )

Avatar du membre
Barthandelus
Niveau 3
Niveau 3
Messages : 46
Enregistré le : mer. 02 janv. 2019 14:34
Status : Hors ligne

Re: Mouse Cursor "Capture".

#5

Message par Barthandelus » lun. 21 oct. 2019 08:06

C'est vrai que ce n'est pas évident. :P

Je vais tenter d'apporter plus de précision : Le curseur de la souris, dans les applications 3D, est "capturé", il disparaît, et même en faisant un mouvement de 2 mètres sur la gauche avec une sensibilité maximale de la souris (ce qui va faire tourner la caméra sur elle même et faire plusieurs tours complets), la souris ne va pas quitter l'application dans le cas d'un dualscreen ou d'une fenêtre réduite.

Un exemple concret sous THREEJS : https://threejs.org/examples/misc_contr ... rlock.html

En cliquant avec la souris (ECHAP pour quitter), le pointeur disparaît, et on peux bouger la souris librement : en mettant la fenêtre du navigateur en 100x100 px, même le plus grand des mouvements de la souris ne fera pas quitter l'application.

Cependant, en prise en main à distance, la souris n'est pas capturée par les applications 3D. Résultat, la souris "quitte" la fenêtre ce qui empêche d'avoir des mouvements de caméra "justes". Le Cloud Gaming via des logiciels non adaptés (souvent gratuit, en vérité, à la différence de ceux qui ne vont pas avoir cette problématique) est donc impossible.

L'idée est donc :
1. De positionner manuellement la souris au centre de la fenêtre de prise en main à distance.
2. D'appuyer sur un shortcut clavier récupérer par le programme AutoIT qui activera le "freez". (Qui fera en gros $MouseAllowMove = false et qui retiendra les coordonnées de la souris)
3. D'appuyer sur un autre shortcut clavier pour "libérer" la souris.

Ma définition du freez :
- Il n'est pas attendu que la souris soit capturée (c'est impossible selon moi)
- Ni qu'elle ne puisse pas du tout bouger (sinon, la caméra ne bougerait pas).
- Il faut donc que le programme "retienne" les coordonnées de la souris lorsque le $MouseAllowMove = false et que chaque 250ms (aléatoirement choisi), la souris revienne aux coordonnées retenues.

Jusque là, mon code initial le fait. Le soucis, c'est qu'effectuer un MouseMove() vers les coordonnées retenues, en speed 0, provoque un mouvement de caméra. Résultat, la caméra va bien sur la gauche dans l'application, mais la souris lorsque la souris revient à sa position initiale, la caméra aussi. Le résultat attendu est donc exactement le même scénario, mais sans que la caméra revienne à sa position initiale. Entre autre, un MouseMove() qui téléporterait la souris sans provoquer un événement dans Windows.

Je reconnais ne pas comprendre l'intégralité de la solution que tu proposes (catch de l’événement de la souris pour simplement l'ignorer ?). Est-ce que tu penses, avec ces informations, que ta solution peut aboutir ?

Répondre