Jump to content
Craigo

_MouseTrap: different behaviour depending on script location

Recommended Posts

Craigo

Hello -

I have found some odd behaviour when testing the "_MouseTrap" function.

Sample code:
 

#include <Misc.au3>
_MouseTrap(300, 300, 400, 400)
Sleep(10000)
_MouseTrap()

When this is saved to a file located on the desktop and executed with a double-click, the function behaves as I believe it should - trapping the mouse pointer within the specified bounds for the duration.

When the same file is saved to a file located in a folder elsewhere (e.g. a subfolder of C: or a network location), the function misbehaves. The mouse pointer is initially relocated and trapped within the specified bounds, but the user can left-click or right-click and immediately release the mouse pointer.

It seems odd that the behaviour should change depending on the location of the script. It is not a filesystem permissions problem.

Environment:

  • Windows 10 1709 Enterprise x64
  • AutoIt 3.3.14.2, 3.3.14.5 (default installer options)

Share this post


Link to post
Share on other sites
Craigo

I have also subsequently tested AutoIt Beta 3.3.15.1, which exhibits the same behaviour.

Share this post


Link to post
Share on other sites
Bilgus

I think This is a limitation of ClipCursor

try this example click Trap, it will happen every time you click because the app loses focus

Now Try Trap4Real it reactivates the window and sets _MouseTrap again and thus it can't escape

Press ESC to release your mouse..

#include <Misc.au3>
#include <GUIConstantsEx.au3>
Global $bTrap = False
Global $bTrap4Real = False
Global $idTrap, $idTrap4Real

HotKeySet("{ESC}", Release)

Example()

Func Example()

    ; Create a GUI with various controls.
    Local $hGUI = GUICreate("Example", 300, 100, 500, 100)
    $idTrap = GUICtrlCreateButton("Trap", 100, 50, 85, 25)
    $idTrap4Real = GUICtrlCreateButton("Trap4Real", 200, 50, 85, 25)
    ; Display the GUI.
    GUISetState(@SW_SHOW, $hGUI)

    ; Loop until the user exits.
    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                ExitLoop
            Case $idTrap
                If $bTrap Then
                    _MouseTrap()
                    $bTrap = False
                    GUICtrlSetData($idTrap, "Trap")
                Else
                    _MouseTrap(300, 100, 400, 200)
                    $bTrap = True
                    GUICtrlSetData($idTrap, "Release")
                EndIf
                
            Case $idTrap4Real
                If $bTrap4Real Then
                    _MouseTrap()
                    $bTrap4Real = False
                    GUICtrlSetData($idTrap4Real, "Trap4Real")
                Else
                    _MouseTrap(300, 100, 400, 200)
                    $bTrap4Real = True
                    GUICtrlSetData($idTrap4Real, "Release")
                EndIf
            Case Else
                If Not WinActive($hGUI) And $bTrap4Real Then
                    WinActivate($hGUI)
                    _MouseTrap(300, 100, 400, 200)
                EndIf
        EndSwitch
    WEnd

    ; Delete the previous GUI and all controls.
    GUIDelete($hGUI)
EndFunc   ;==>Example

Func Release()
    _MouseTrap()
    $bTrap4Real = False
    GUICtrlSetData($idTrap4Real, "Trap4Real")
    $bTrap = False
    GUICtrlSetData($idTrap, "Trap")
EndFunc   ;==>Release

 

Edited by Bilgus

Share this post


Link to post
Share on other sites
Craigo

Thanks, Bilgus.

My use case currently only has a SplashText. Can that even have or lose focus? If your workaround (which does indeed work) can be applied in that scenario, fantastic. I'll give it a go. If it isn't going to work for a SplashText, I guess I can retool my code to use a GUI...

For reference, my current code is below. It is using the less-capable but probably sufficient _MouseTrap() because BlockInput() needs #RequireAdmin (a dealbreaker).

#include <String.au3>
#include <Misc.au3>

If StringInStr(@OSArch, "64") <> 0 Then
  $RegHive = "HKLM64"
Else
  $RegHive = "HKLM"
EndIf

$PopupWidth          = 410
$PopupHeight         = 160
$MouseTrapLeftEdge   = (@DesktopWidth  / 2) - ($PopupWidth  / 2)
$MouseTrapTopEdge    = (@DesktopHeight / 2) - ($PopupHeight / 2)
$MouseTrapRightEdge  = (@DesktopWidth  / 2) + ($PopupWidth  / 2)
$MouseTrapBottomEdge = (@DesktopHeight / 2) + ($PopupHeight / 2)
$TextBase = "Application installation in progress." & @CRLF & @CRLF & "User input will be restricted for the duration of this process." & @CRLF & @CRLF

If RegRead($RegHive & "\Software\InHouse", "AppDeploymentInProgress") = 1 Then
  SplashTextOn("In-House Application Installation", $TextBase, $PopupWidth, $PopupHeight, -1, -1, 4)
  _MouseTrap($MouseTrapLeftEdge, $MouseTrapTopEdge, $MouseTrapRightEdge, $MouseTrapBottomEdge)
  While RegRead($RegHive & "\Software\InHouse", "AppDeploymentInProgress") = 1
    For $i = 0 To 3
      $TextToDisplay = $TextBase & _StringRepeat("   ", $i) & "•"
      ControlSetText("In-House Application Installation", "", "Static1", $TextToDisplay)
      Sleep(1000)
    Next
    For $i = 4 To 1 Step -1
      $TextToDisplay = $TextBase & _StringRepeat("   ", $i) & "•"
      ControlSetText("In-House Application Installation", "", "Static1", $TextToDisplay)
      Sleep(1000)
    Next
  WEnd
EndIf
SplashOff()
_MouseTrap()

 

Share this post


Link to post
Share on other sites
Bilgus

Personally I don't like the idea of trapping the mouse but SplashTextOn does return a hWnd

#include <AutoItConstants.au3>
#include <Misc.au3>

Local $hWnd = SplashTextOn("Title", "Message goes here.", -1, -1, -1, -1, $DLG_TEXTLEFT, "", 24)
WinActivate($hWnd)
Local $aPos = WinGetPos($hWnd)
If IsArray($aPos) Then
    ConsoleWrite(StringFormat("X: %d Y: %d W: %d H: %d", $aPos[0], $aPos[1], $aPos[2], $aPos[3]) & @CRLF)
    _MouseTrap($aPos[0], $aPos[1], $aPos[0] + $aPos[2], $aPos[1] + $aPos[3] + 50)

    While WinWaitNotActive($hWnd, "", 10) <> 0
        ConsoleWrite("De-Activated" & @CRLF)
        WinActivate($hWnd)
        _MouseTrap($aPos[0], $aPos[1], $aPos[0] + $aPos[2], $aPos[1] + $aPos[3] + 50)
    WEnd

    _MouseTrap()
Else
    ConsoleWrite("Invalid" & @CRLF)
EndIf
SplashOff()

 

Share this post


Link to post
Share on other sites
Bilgus

Do note the +50 extra added to the height so you can click off the window

Share this post


Link to post
Share on other sites
Craigo

Thanks again, Bilgus.

I agree that messing with the user's input ability is a little heavy-handed, but that's what I have been tasked to do. Can't have users restarting their computers in the middle of an app deployment!

Your code was very helpful. In the end, I have a pretty tidy solution:

  • An Adlib function that ensures the splashtext maintains focus
  • Moved the registry test to an Adlib function (with a sizeable delay)
  • I nabbed your idea of using WinGetPos to return the splashtext position/size (much more flexible)
  • A hotkey to toggle mouse trapping
  • Like 1

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.