Help with cursor hiding script Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
Hitaku
Posts: 17
Joined: 14 Mar 2017, 00:57

Help with cursor hiding script

30 Jun 2017, 06:43

The below script seems to work perfectly when I press ScrollLock, but I was hoping to have it work without having to press any keys if a window was active. Where exactly do I place #IfWinActive? Could someone help me out with editing this? For the sake of simplicity, lets just use #IfWinActive, Paint.

Code: Select all

ScrollLock::
if (flag := !flag) {
   MouseGetPos, , , hwnd
   Gui Cursor:+Owner%hwnd%
   BlockInput MouseMove
   DllCall("ShowCursor", Int,0)
} else {
   BlockInput MouseMoveOff
   DllCall("ShowCursor", Int,1)
}
Return
BoBo
Posts: 6564
Joined: 13 May 2014, 17:15

Re: Help with cursor hiding script

30 Jun 2017, 06:59

Hitaku wrote:[...] but I was hoping to have it work without having to press any keys [...]
#IfWinActive / #IfWinExist
Creates context-sensitive hotkeys and hotstrings. Such hotkeys perform a different action (or none at all) depending on the type of window that is active or exists.
As far as I can say you've to use SetTimer to do checks against the window itself (+ ControlGetFocus/CoordMode/...) to get this done.
Hitaku
Posts: 17
Joined: 14 Mar 2017, 00:57

Re: Help with cursor hiding script

30 Jun 2017, 10:09

I see. I've never used those before. Would you maybe be able to assist me in changing the script to use that instead?
BoBo
Posts: 6564
Joined: 13 May 2014, 17:15

Re: Help with cursor hiding script

30 Jun 2017, 11:20

Code: Select all

#Persistent
SetTitleMatchMode, 2

SetTimer, Painter, 100
Return

Painter:
WinGetTitle, Title, A
If InStr(Title,"Paint")
   WinGetPos, X, Y, Width, Height, A
<now you've to create a condition based on the current mouse position and its position within the target windows frame>
Return
Good luck :)
wolf_II
Posts: 2688
Joined: 08 Feb 2015, 20:55

Re: Help with cursor hiding script

30 Jun 2017, 12:12

There is another way with SHELLHOOK that allows you to monitor (and respond to) the active window.
Forum user SvenBent explains the benefits of SHELLHOOK over SetTimer here: https://autohotkey.com/boards/viewtopic ... 26#p109226
It works like this: Put a Watchdog function in your script and have it alert the Guard whenever the active window changes.

Example with notepad: (Paint does not play nicely with hiding cursor)

Code: Select all

SetBatchLines, -1
Return ; end of auto-execute section



;-------------------------------------------------------------------------------
Watchdog(wParam, lParam := "") { ; monitor activating windows
;-------------------------------------------------------------------------------
    static init   := DllCall("RegisterShellHookWindow", Ptr, A_ScriptHwnd)
        , MsgNum  := DllCall("RegisterWindowMessage", Str, "SHELLHOOK")
        , neglect := OnMessage(MsgNum, "Watchdog")
        , CleanUp := {base: {__Delete: "Watchdog"}}

    If Not IsObject(CleanUp) {
        OnMessage(MsgNum, "")
        DllCall("DeregisterShellHookWindow", Ptr, A_ScriptHwnd)
    }

    If (wParam = 1)     ; HSHELL_WINDOWCREATED
    Or (wParam = 4)     ; HSHELL_WINDOWACTIVATED
    Or (wParam = 32772) ; HSHELL_RUDEAPPACTIVATED

        Guard(lParam) ; alert the guard about a new active window
}



;-------------------------------------------------------------------------------
Guard(hActive) { ; toggle mouse on/off if a certain window is active
;-------------------------------------------------------------------------------
    WinGetTitle, Title, ahk_id %hActive%

    If InStr(Title, "Notepad") {        ; toggle mouse off
        MouseGetPos,,, hwnd
        Gui, Cursor: +Owner%hwnd%
        BlockInput, MouseMove
        DllCall("ShowCursor", Int,0)
    }

    Else {                              ; toggle mouse on
        BlockInput, MouseMoveOff
        DllCall("ShowCursor", Int,1)
    }
}
Hitaku
Posts: 17
Joined: 14 Mar 2017, 00:57

Re: Help with cursor hiding script

01 Jul 2017, 08:23

wolf_II wrote:There is another way with SHELLHOOK that allows you to monitor (and respond to) the active window.
Forum user SvenBent explains the benefits of SHELLHOOK over SetTimer here: https://autohotkey.com/boards/viewtopic ... 26#p109226
It works like this: Put a Watchdog function in your script and have it alert the Guard whenever the active window changes.

Example with notepad: (Paint does not play nicely with hiding cursor)

Code: Select all

SetBatchLines, -1
Return ; end of auto-execute section



;-------------------------------------------------------------------------------
Watchdog(wParam, lParam := "") { ; monitor activating windows
;-------------------------------------------------------------------------------
    static init   := DllCall("RegisterShellHookWindow", Ptr, A_ScriptHwnd)
        , MsgNum  := DllCall("RegisterWindowMessage", Str, "SHELLHOOK")
        , neglect := OnMessage(MsgNum, "Watchdog")
        , CleanUp := {base: {__Delete: "Watchdog"}}

    If Not IsObject(CleanUp) {
        OnMessage(MsgNum, "")
        DllCall("DeregisterShellHookWindow", Ptr, A_ScriptHwnd)
    }

    If (wParam = 1)     ; HSHELL_WINDOWCREATED
    Or (wParam = 4)     ; HSHELL_WINDOWACTIVATED
    Or (wParam = 32772) ; HSHELL_RUDEAPPACTIVATED

        Guard(lParam) ; alert the guard about a new active window
}



;-------------------------------------------------------------------------------
Guard(hActive) { ; toggle mouse on/off if a certain window is active
;-------------------------------------------------------------------------------
    WinGetTitle, Title, ahk_id %hActive%

    If InStr(Title, "Notepad") {        ; toggle mouse off
        MouseGetPos,,, hwnd
        Gui, Cursor: +Owner%hwnd%
        BlockInput, MouseMove
        DllCall("ShowCursor", Int,0)
    }

    Else {                              ; toggle mouse on
        BlockInput, MouseMoveOff
        DllCall("ShowCursor", Int,1)
    }
}

When I tried this script out, it worked great, but if I tab out / tab back in the cursor shows again. It's not active anymore, but it still shows. Is there a fix to that?
wolf_II
Posts: 2688
Joined: 08 Feb 2015, 20:55

Re: Help with cursor hiding script  Topic is solved

01 Jul 2017, 13:34

Hitaku wrote:Is there a fix to that?
I think there is a way, but I don't like it very much. :( I had to get rid of your very elegant Gui Cursor and DllCall, and use a separate function to show/hide the mouse cursor.
This is a function I found somewhere on this forum and edited the hell out of. (A bad thing I do to understand other people's code.)

Where did you first read about this Gui Cursor:+Owner%hwnd% :?: I have not seen that used like that before, I would like to read more about its use and maybe use it again for this thread.
I presume, it does not like being inside a function? :think:
Meanwhile, here is a possible alternative:
Hitaku
Posts: 17
Joined: 14 Mar 2017, 00:57

Re: Help with cursor hiding script

01 Jul 2017, 16:12

Your alternative script worked perfectly for me! As for the script I originally linked, it was something that I picked up from a previous thread so I don't know much about that function. I'm sorry. =(

Thank you all though for taking the time to help me, happy I ended up with something that worked.
zertrax

Re: Help with cursor hiding script

04 Aug 2017, 15:47

Hello there,

Is it possible to globally hide the cursor after X seconds of inactivity while turning on/off the script with a shortcut?
Some programs change name and the window name solution may not always work
SkyBreather
Posts: 12
Joined: 25 May 2016, 13:37

Re: Help with cursor hiding script

02 Oct 2017, 01:38

Is there anyway to get the script to stay on top? Whenever I use that script on a certain window, and then alt+tab to a different one the mouse is shown. Is there anyway to avoid this conundrum? (P.S: I removed the BlockInput command)
wolf_II
Posts: 2688
Joined: 08 Feb 2015, 20:55

Re: Help with cursor hiding script

02 Oct 2017, 07:29

Conundrum
Last edited by wolf_II on 02 Oct 2017, 11:42, edited 1 time in total.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Help with cursor hiding script

02 Oct 2017, 08:05

Hello wolf_II
wolf_II wrote:

Code: Select all

ShowMouse()
I take this one, thanks :wave: (I change BlankCursor to be static and make it only once though.)

Cheers.
wolf_II
Posts: 2688
Joined: 08 Feb 2015, 20:55

Re: Help with cursor hiding script

02 Oct 2017, 09:44

Hi Helgef, :wave:

Thank you for the suggestion. Excellent.
  • While I was at it, I implemented the protect local vars from interfering globals that the user might put up, that I learned from you.
  • While I was at it, I also decided to use e.g. "Int" over Int and so on, since omitting the quotes seems to create variables named Int and so on.
  • I then commented every parameter to a WinAPI DllCall with the TYPE of info the API expects for this parameter.
    I included links to MSDN pages where I got all the comments from, the translation from a comment like "HCURSOR" to "Ptr" is my own. (and may be wrong :oops: )

Code: Select all

;-------------------------------------------------------------------------------
show_Mouse(bShow := True) { ; show/hide the mouse cursor
;-------------------------------------------------------------------------------
    ; WINAPI: SystemParametersInfo, CreateCursor, CopyImage, SetSystemCursor
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/ms724947.aspx
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/ms648385.aspx
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/ms648031.aspx
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/ms648395.aspx
    ;---------------------------------------------------------------------------
    static BlankCursor
    static CursorList := "32512, 32513, 32514, 32515, 32516, 32640, 32641"
        . ",32642, 32643, 32644, 32645, 32646, 32648, 32649, 32650, 32651"
    local ANDmask, XORmask, CursorHandle

    If bShow ; shortcut for showing the mouse cursor
        Return, DllCall("SystemParametersInfo"
            , "UInt", 0x57              ; UINT  uiAction    (SPI_SETCURSORS)
            , "UInt", 0                 ; UINT  uiParam
            , "Ptr",  0                 ; PVOID pvParam
            , "UInt", 0)                ; UINT  fWinIni

    If Not BlankCursor { ; create BlankCursor only once
        VarSetCapacity(ANDmask, 32 * 4, 0xFF)
        VarSetCapacity(XORmask, 32 * 4, 0x00)
        BlankCursor := DllCall("CreateCursor"
            , "Ptr", 0                  ; HINSTANCE  hInst
            , "Int", 0                  ; int        xHotSpot
            , "Int", 0                  ; int        yHotSpot
            , "Int", 32                 ; int        nWidth
            , "Int", 32                 ; int        nHeight
            , "Ptr", &ANDmask           ; const VOID *pvANDPlane
            , "Ptr", &XORmask)          ; const VOID *pvXORPlane
    }

    ; set all system cursors to blank, each needs a new copy
    Loop, Parse, CursorList, `,, %A_Space%
    {
        CursorHandle := DllCall("CopyImage"
            , "Ptr",  BlankCursor       ; HANDLE hImage
            , "UInt", 2                 ; UINT   uType      (IMAGE_CURSOR)
            , "Int",  0                 ; int    cxDesired
            , "Int",  0                 ; int    cyDesired
            , "UInt", 0)                ; UINT   fuFlags
        DllCall("SetSystemCursor"
            , "Ptr",  CursorHandle      ; HCURSOR hcur
            , "UInt", A_Loopfield)      ; DWORD   id
    }
}
Edit: May it's protect globel vars that the user might have put up from interference by this function. Maybe it's both.
In any case, it's making up for a missing local command, that would do the same, when called without arguments.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Help with cursor hiding script

02 Oct 2017, 10:31

Excellent wolf_II :thumbup:
"Int" over Int and so on, since omitting the quotes seems to create variables named Int and so on.
This is my preference, mostly due to syntax highligthing. I checked with DebugVars, omitting the quotes doesn't seem to create any Int variable. Also, having a global variable Int:="somethingIncorrectForDllCall" doesn't seem to affect the dllcall either.
"HCURSOR" to "Ptr"
That is correct.

Cheers.
--- > Scripts and Functions < ---
wolf_II
Posts: 2688
Joined: 08 Feb 2015, 20:55

Re: Help with cursor hiding script

02 Oct 2017, 11:14

Thanks for responding!
Helgef wrote:omitting the quotes doesn't seem to create any Int variable
DebugVars does show them, and ListVars does. Please check the following stand-alone script. Int is listed under global vars.

Next "iteration" of this function
  • use two temporary added lines for debug/demo
  • "Int" replaced by Int, for demo (also temporary)
  • every DllCall's return value is now commented with TYPE info as well

Code: Select all

;-------------------------------------------------------------------------------
; this example hides the mouse cursor for 5 seconds, then shows it again
;-------------------------------------------------------------------------------
    show_Mouse(False)
    Sleep, 5000
    show_Mouse(True)

ExitApp ; end of auto-execute section



;-------------------------------------------------------------------------------
show_Mouse(bShow := True) { ; show/hide the mouse cursor
;-------------------------------------------------------------------------------
    ; WINAPI: SystemParametersInfo, CreateCursor, CopyImage, SetSystemCursor
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/ms724947.aspx
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/ms648385.aspx
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/ms648031.aspx
    ; https://msdn.microsoft.com/en-us/library/windows/desktop/ms648395.aspx
    ;---------------------------------------------------------------------------
    static BlankCursor
    static CursorList := "32512, 32513, 32514, 32515, 32516, 32640, 32641"
        . ",32642, 32643, 32644, 32645, 32646, 32648, 32649, 32650, 32651"
    local ANDmask, XORmask, CursorHandle

ListVars ; debug/demo
MsgBox   ; debug/demo

    If bShow ; shortcut for showing the mouse cursor

        Return, DllCall("SystemParametersInfo"
            , "UInt", 0x57              ; UINT  uiAction    (SPI_SETCURSORS)
            , "UInt", 0                 ; UINT  uiParam
            , "Ptr",  0                 ; PVOID pvParam
            , "UInt", 0                 ; UINT  fWinIni
            , "Cdecl Int")              ; return BOOL

    If Not BlankCursor { ; create BlankCursor only once
        VarSetCapacity(ANDmask, 32 * 4, 0xFF)
        VarSetCapacity(XORmask, 32 * 4, 0x00)

        BlankCursor := DllCall("CreateCursor"
            , "Ptr", 0                  ; HINSTANCE  hInst
            , Int  , 0                  ; int        xHotSpot
            , Int  , 0                  ; int        yHotSpot
            , Int  , 32                 ; int        nWidth
            , Int  , 32                 ; int        nHeight
            , "Ptr", &ANDmask           ; const VOID *pvANDPlane
            , "Ptr", &XORmask           ; const VOID *pvXORPlane
            , "Cdecl Ptr")              ; return HCURSOR
    }

    ; set all system cursors to blank, each needs a new copy
    Loop, Parse, CursorList, `,, %A_Space%
    {
        CursorHandle := DllCall("CopyImage"
            , "Ptr",  BlankCursor       ; HANDLE hImage
            , "UInt", 2                 ; UINT   uType      (IMAGE_CURSOR)
            , Int  ,  0                 ; int    cxDesired
            , Int  ,  0                 ; int    cyDesired
            , "UInt", 0                 ; UINT   fuFlags
            , "Cdecl Ptr")              ; return HANDLE

        DllCall("SetSystemCursor"
            , "Ptr",  CursorHandle      ; HCURSOR hcur
            , "UInt", A_Loopfield       ; DWORD   id
            , "Cdecl Int")              ; return BOOL
    }
}
Edit I only just noticed your tiny writing ... I assume you encourage me to post there ... Rather than going on offtopic here ... Ok then, will do!
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Help with cursor hiding script

02 Oct 2017, 11:37

You are right, my eyes where not doing their job. :crazy:
Note: CreateCursor SystemParametersInfo, CopyImage and SetSystemCursor uses the WINAPI calling convention, which is defined as stdcall, which is the default for DllCall, hence, cdecl should be omitted.
Your assumption was correct.

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: ArkuS, Descolada and 131 guests