Please help complete this script(confining mouse to a window)

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
tatagi
Posts: 181
Joined: 23 Aug 2018, 11:17

Please help complete this script(confining mouse to a window)

29 Sep 2020, 06:52

Code: Select all

Success:=ClipCursor(true,0,0,1918,A_ScreenHeight)
DetectHiddenWindows, On
WinGet, hwnd, ID, % "ahk_pid " DllCall("GetCurrentProcessId")
DllCall( "RegisterShellHookWindow", UInt,hWnd )
MsgNum := DllCall( "RegisterWindowMessage", Str,"SHELLHOOK" )
OnMessage( MsgNum, "ShellMessage" )
Return

ShellMessage( wParam,lParam ) {
Success:=ClipCursor(True,0,0,1918,A_ScreenHeight)
}


ClipCursor(Confine,x1,y1,x2,y2) 
	{
	If !Confine
		return DllCall("ClipCursor")
	VarSetCapacity(R,16,0)
	NumPut(x1,&R,0,"UInt")
	NumPut(y1,&R,4,"UInt")
	NumPut(x2,&R,8,"UInt")
	NumPut(y2,&R,12,"UInt")
	Return DllCall("ClipCursor", UInt,&R)
	}


f4::exitapp

this code restricts the mouse area to part of the screen, and it works perfectly.

but I want this to work only when notepad is active.

is it possible ?
User avatar
mikeyww
Posts: 26931
Joined: 09 Sep 2014, 18:38

Re: Please help complete this script(confining mouse to a window)

29 Sep 2020, 07:40

It looks like Confine is a flag, so you could try adding a conditional statement to the ShellMessage function, such that if Notepad is active, it sends a False instead of True for that parameter.
tatagi
Posts: 181
Joined: 23 Aug 2018, 11:17

Re: Please help complete this script(confining mouse to a window)

29 Sep 2020, 07:55

mikeyww wrote:
29 Sep 2020, 07:40
It looks like Confine is a flag, so you could try adding a conditional statement to the ShellMessage function, such that if Notepad is active, it sends a False instead of True for that parameter.
hello.

this is found somewhere in the forum and how this works is completely out of the scope of my knowledge.


could you pls suggest the working script for this purpose? would appreciate it much!

it should:

1. hotkey sends the command no matter what program is currently active.
2. when hotkey is pressed, the mouse lock area should be made only for notepad.
User avatar
mikeyww
Posts: 26931
Joined: 09 Sep 2014, 18:38

Re: Please help complete this script(confining mouse to a window)

29 Sep 2020, 08:14

Would try contacting the person who wrote the script.
A_AhkUser
Posts: 1147
Joined: 06 Mar 2017, 16:18
Location: France
Contact:

Re: Please help complete this script(confining mouse to a window)

29 Sep 2020, 10:17

The following seems to work (I'm not really familiar with DllCalls and Win API stuffs but gurus might be able to correct the code, as the case may be):

Code: Select all

#NoEnv
#Warn
SendMode Input
SetWorkingDir %A_ScriptDir%
#SingleInstance force

winTitle := "ahk_class Notepad"
!x::ExitApp


OnActivate(hActivation:=-1) { ; https://docs.microsoft.com/en-us/windows/win32/menurc/using-cursors#confining-a-cursor
	local
	static rcOldClip := ""
	static hOldActivation := ""
	if (hActivation) {
		((hActivation <> -1) && hOldActivation:=hActivation)
		VarSetCapacity(rcOldClip, 16, 0) ; previous area for ClipCursor
		DllCall("User32.dll\GetClipCursor", "Ptr", &rcOldClip) ; Record the area in which the cursor can move.
		VarSetCapacity(rcClip, 16, 0) ; new area for ClipCursor
		DllCall("User32.dll\GetWindowRect", "Ptr", hOldActivation, "Ptr", &rcClip) ; Get the dimensions of the application's window.
		DllCall("User32.dll\ClipCursor", "Ptr", &rcClip) ; Confine the cursor to the application's window.
		SetTimer % A_ThisFunc, 100
	} else {
		SetTimer % A_ThisFunc, Off
		(rcOldClip && DllCall("User32.dll\ClipCursor", "Ptr", &rcOldClip), rcOldClip:="") ; Restore the cursor to its previous area.
	}
}
; =====================================
shellMessage(wParam, lParam) { ; based on https://autohotkey.com/board/topic/80644-how-to-hook-on-to-shell-to-receive-its-messages/
	local
	global winTitle
	static f := (Func("OnActivate")
			, DllCall("RegisterShellHookWindow", "Ptr", A_ScriptHwnd)
			, OnMessage(DllCall("RegisterWindowMessage", "Str", "SHELLHOOK"), "shellMessage")
			, OnExit("shellMessage"))
	static iRcOldClip := ""
	static _ := (VarSetCapacity(iRcOldClip, 16, 0) ; the very initial area for ClipCursor
			, DllCall("User32.dll\GetClipCursor", "Ptr", &iRcOldClip)) ; Record the initial area in which the cursor can move.
	Critical
	if (wParam = A_ExitReason) {
		return 0, DllCall("DeregisterShellHookWindow", "UInt", A_ScriptHwnd), DllCall("User32.dll\ClipCursor", "Ptr", &iRcOldClip) ; Restore the cursor to its very initial area. 
	}
	if ((wParam = 32772) or (wParam = 4)) { ; HSHELL_WINDOWACTIVATED := 4, HSHELL_RUDEAPPACTIVATED := 32772
		fn := f.bind(WinActive(winTitle))
		SetTimer % fn, -1
	}
}

A_AhkUser
my scripts
tatagi
Posts: 181
Joined: 23 Aug 2018, 11:17

Re: Please help complete this script(confining mouse to a window)

29 Sep 2020, 19:10

A_AhkUser wrote:
29 Sep 2020, 10:17
The following seems to work (I'm not really familiar with DllCalls and Win API stuffs but gurus might be able to correct the code, as the case may be):

Code: Select all

#NoEnv
#Warn
SendMode Input
SetWorkingDir %A_ScriptDir%
#SingleInstance force

winTitle := "ahk_class Notepad"
!x::ExitApp


OnActivate(hActivation:=-1) { ; https://docs.microsoft.com/en-us/windows/win32/menurc/using-cursors#confining-a-cursor
	local
	static rcOldClip := ""
	static hOldActivation := ""
	if (hActivation) {
		((hActivation <> -1) && hOldActivation:=hActivation)
		VarSetCapacity(rcOldClip, 16, 0) ; previous area for ClipCursor
		DllCall("User32.dll\GetClipCursor", "Ptr", &rcOldClip) ; Record the area in which the cursor can move.
		VarSetCapacity(rcClip, 16, 0) ; new area for ClipCursor
		DllCall("User32.dll\GetWindowRect", "Ptr", hOldActivation, "Ptr", &rcClip) ; Get the dimensions of the application's window.
		DllCall("User32.dll\ClipCursor", "Ptr", &rcClip) ; Confine the cursor to the application's window.
		SetTimer % A_ThisFunc, 100
	} else {
		SetTimer % A_ThisFunc, Off
		(rcOldClip && DllCall("User32.dll\ClipCursor", "Ptr", &rcOldClip), rcOldClip:="") ; Restore the cursor to its previous area.
	}
}
; =====================================
shellMessage(wParam, lParam) { ; based on https://autohotkey.com/board/topic/80644-how-to-hook-on-to-shell-to-receive-its-messages/
	local
	global winTitle
	static f := (Func("OnActivate")
			, DllCall("RegisterShellHookWindow", "Ptr", A_ScriptHwnd)
			, OnMessage(DllCall("RegisterWindowMessage", "Str", "SHELLHOOK"), "shellMessage")
			, OnExit("shellMessage"))
	static iRcOldClip := ""
	static _ := (VarSetCapacity(iRcOldClip, 16, 0) ; the very initial area for ClipCursor
			, DllCall("User32.dll\GetClipCursor", "Ptr", &iRcOldClip)) ; Record the initial area in which the cursor can move.
	Critical
	if (wParam = A_ExitReason) {
		return 0, DllCall("DeregisterShellHookWindow", "UInt", A_ScriptHwnd), DllCall("User32.dll\ClipCursor", "Ptr", &iRcOldClip) ; Restore the cursor to its very initial area. 
	}
	if ((wParam = 32772) or (wParam = 4)) { ; HSHELL_WINDOWACTIVATED := 4, HSHELL_RUDEAPPACTIVATED := 32772
		fn := f.bind(WinActive(winTitle))
		SetTimer % fn, -1
	}
}

A_AhkUser

Thanks for the script. It seems to be very well built one.
but forgive me that I am very basic level autohotkeyer so...


1. The example script you posted restrict cursor placement in the bottom of the screen(similar to taskbar). Where in the script should I put my own coordinates of restricted mouse area? For example in my original post, the line ClipCursor(true,0,0,1918,A_ScreenHeight) indicates my cursor can be placed from x0 y0 to x1918 y screenheight. How do I apply the value in this script?


2. I tend to panic when I see a large, complicated script for fear of how cpu heavy the script is gonna get :? That's why I usually prefer to avoid #persistent or Loop syntax.
I checked the windows task manager and it seems to be steady low just like other script I already use, but I ask this for double check.
A_AhkUser
Posts: 1147
Joined: 06 Mar 2017, 16:18
Location: France
Contact:

Re: Please help complete this script(confining mouse to a window)

30 Sep 2020, 11:56

@tatagi

1. Try this:

Code: Select all

#NoEnv
#Warn
SendMode Input
SetWorkingDir %A_ScriptDir%
#SingleInstance force

area := {x: 200, y: 200, w: 700, h: 700}
winTitle := "ahk_class Notepad"
return

!x::ExitApp


OnActivate(hMatch) { ; https://docs.microsoft.com/en-us/windows/win32/menurc/using-cursors#confining-a-cursor
	local
	global area
	static rcOldClip := ""
	if (hMatch) {
		VarSetCapacity(rcOldClip, 16, 0) ; previous area for ClipCursor
		DllCall("User32.dll\GetClipCursor", "Ptr", &rcOldClip) ; Record the area in which the cursor can move.
		VarSetCapacity(rcClip, 16, 0) ; new area for ClipCursor
		; for each, value in area {
			; NumPut(value, &rcClip, (a_index -1) * 4, "UInt")
		; }
		NumPut(area.x, &rcClip, 0, "UInt")
		NumPut(area.y, &rcClip, 4, "UInt")
		NumPut(area.w, &rcClip, 8, "UInt")
		NumPut(area.h, &rcClip, 12, "UInt")
		DllCall("User32.dll\ClipCursor", "Ptr", &rcClip) ; Confine the cursor to the application's window.
	} else {
		(rcOldClip && DllCall("User32.dll\ClipCursor", "Ptr", &rcOldClip), rcOldClip:="") ; Restore the cursor to its previous area.
	}
}
; =====================================
shellMessage(wParam, lParam) { ; based on https://autohotkey.com/board/topic/80644-how-to-hook-on-to-shell-to-receive-its-messages/
	local
	global winTitle
	static f := (Func("OnActivate")
			, DllCall("RegisterShellHookWindow", "Ptr", A_ScriptHwnd)
			, OnMessage(DllCall("RegisterWindowMessage", "Str", "SHELLHOOK"), "shellMessage")
			, OnExit("shellMessage"))
	static iRcOldClip := ""
	static _ := (VarSetCapacity(iRcOldClip, 16, 0) ; the very initial area for ClipCursor
			, DllCall("User32.dll\GetClipCursor", "Ptr", &iRcOldClip)) ; Record the initial area in which the cursor can move.
	Critical
	if (wParam = A_ExitReason) {
		return 0, DllCall("DeregisterShellHookWindow", "UInt", A_ScriptHwnd), DllCall("User32.dll\ClipCursor", "Ptr", &iRcOldClip) ; Restore the cursor to its very initial area.
	}
	if ((wParam = 32772) or (wParam = 4)) { ; HSHELL_WINDOWACTIVATED := 4, HSHELL_RUDEAPPACTIVATED := 32772
		fn := f.bind(WinActive(winTitle))
		SetTimer % fn, -1
	}
}
2. Large, complicated script does not necessarly means heavy in terms of CPU resources. DllCall in particular does not mean heavy use of resources:

Code: Select all

VarSetCapacity(rcClip, 16, 0) ; new area for ClipCursor
DllCall("User32.dll\GetWindowRect", "Ptr", hOldActivation, "Ptr", &rcClip)
can somehow be seen as an equivalent of a given use of WinGetPos while:

Code: Select all

DllCall("Sleep", "UInt", 500)
(not present in the script this time, so just for illustrative purpose) can be used in place of:

Code: Select all

sleep, 500
to make the script merely... sleep :yawn:

The first script does not loop but uses a timed subroutine in order to update, if need be, the confinement area (if the target window appears to have been resized/moved since the last ClipCursor call). In this script, the checking is set with a period of 100ms, which I found to be a good balance between real-time updating and efficiency (the timer running, what is more, only when notepad is active). Regarding Notepad activation/deactivation detection, the behaviour is the same as with the other script I provided you somewhere else recently: the script does not loop but intercept application events before giving control back to the application (hook): it actually handles it only if the given event fires. In the second script, you have even less reasons to have such resources using concerns: since you want to use a static confinement area, i simply remove the timer; there only remains the hook.


Can someone explain me why in the script above and in the given subset:

Code: Select all

; (...)
; for each, value in area {
	; NumPut(value, &rcClip, (a_index -1) * 4, "UInt")
; }
NumPut(area.x, &rcClip, 0, "UInt")
NumPut(area.y, &rcClip, 4, "UInt")
NumPut(area.w, &rcClip, 8, "UInt")
NumPut(area.h, &rcClip, 12, "UInt")
; (...)
the commented part does not work unlike the four following lines - and while they should be regarded as equivalent (unless I missing something obvious)? Thanks


A_AhkUser
my scripts
tatagi
Posts: 181
Joined: 23 Aug 2018, 11:17

Re: Please help complete this script(confining mouse to a window)

30 Sep 2020, 21:32

@A_AhkUser


Thank you once again for the informative explanation.

Now it works perfectly except one thing; when merging this script into my own one, there's warning saying:

"this line will never execute, due to return preceding it." Mostly it pops up where the line "Return" is placed.


I copied & pasted your entire script on the top, and it looks something like this:

Code: Select all

#NoEnv
#Warn
SendMode Input
SetWorkingDir %A_ScriptDir%
#SingleInstance force

winTitle := "ahk_class Notepad"
!x::ExitApp


OnActivate(hActivation:=-1) { ; https://docs.microsoft.com/en-us/windows/win32/menurc/using-cursors#confining-a-cursor
	local
	static rcOldClip := ""
	static hOldActivation := ""
	if (hActivation) {
		((hActivation <> -1) && hOldActivation:=hActivation)
		VarSetCapacity(rcOldClip, 16, 0) ; previous area for ClipCursor
		DllCall("User32.dll\GetClipCursor", "Ptr", &rcOldClip) ; Record the area in which the cursor can move.
		VarSetCapacity(rcClip, 16, 0) ; new area for ClipCursor
		DllCall("User32.dll\GetWindowRect", "Ptr", hOldActivation, "Ptr", &rcClip) ; Get the dimensions of the application's window.
		DllCall("User32.dll\ClipCursor", "Ptr", &rcClip) ; Confine the cursor to the application's window.
		SetTimer % A_ThisFunc, 100
	} else {
		SetTimer % A_ThisFunc, Off
		(rcOldClip && DllCall("User32.dll\ClipCursor", "Ptr", &rcOldClip), rcOldClip:="") ; Restore the cursor to its previous area.
	}
}
; =====================================
shellMessage(wParam, lParam) { ; based on https://autohotkey.com/board/topic/80644-how-to-hook-on-to-shell-to-receive-its-messages/
	local
	global winTitle
	static f := (Func("OnActivate")
			, DllCall("RegisterShellHookWindow", "Ptr", A_ScriptHwnd)
			, OnMessage(DllCall("RegisterWindowMessage", "Str", "SHELLHOOK"), "shellMessage")
			, OnExit("shellMessage"))
	static iRcOldClip := ""
	static _ := (VarSetCapacity(iRcOldClip, 16, 0) ; the very initial area for ClipCursor
			, DllCall("User32.dll\GetClipCursor", "Ptr", &iRcOldClip)) ; Record the initial area in which the cursor can move.
	Critical
	if (wParam = A_ExitReason) {
		return 0, DllCall("DeregisterShellHookWindow", "UInt", A_ScriptHwnd), DllCall("User32.dll\ClipCursor", "Ptr", &iRcOldClip) ; Restore the cursor to its very initial area. 
	}
	if ((wParam = 32772) or (wParam = 4)) { ; HSHELL_WINDOWACTIVATED := 4, HSHELL_RUDEAPPACTIVATED := 32772
		fn := f.bind(WinActive(winTitle))
		SetTimer % fn, -1
	}
}

;and here comes my script

setstorecapslockmode, off
setcapslockstate, off
#inputlevel 1
hotkey, e, off
hotkey, r, off
capslock::vkFF   ;remaps capslock into unassigned vkFF
#inputlevel 0   ;instead of "capslock & ..."  use "vkFF & ..."
vkFF & 0::   ;turns capslock on and off
setcapslockstate % !getkeystate("capslock", "t")
return

#maxhotkeysperinterval 200
#hotkeyinterval 100
setbatchlines, -1
setkeydelay, -1

vkFF & e::
sendInput {wheelup}
hotkey, e, on
settimer, block_e, 300
return

e::
return

block_e:
hotkey, e, off
settimer, block_e, off
return

vkFF & r::
sendInput {wheeldown}
hotkey, r, on
settimer, block_r, 300
return

r::
return

block_r:
hotkey, r, off
settimer, block_r, off
return

!up::soundset +2
return

!down::soundset -2
return

vkFF & a::
ifwinexist, ahk_class CabinetWClass
winclose
else
run c:\users\lovejoy\downloads, , max
return
this is not my entire script, but I think this suffices to describe what goes wrong because most of my script is just a list of simple hotkeys that run a program or send another keycombo.. it already gives 4 error msgbox.

if I separately run two scripts , the problem does not occur.
A_AhkUser
Posts: 1147
Joined: 06 Mar 2017, 16:18
Location: France
Contact:

Re: Please help complete this script(confining mouse to a window)

01 Oct 2020, 07:38

@tatagi

You might need to simply remove

Code: Select all

!x::ExitApp
on the top of the script (not tested), otherwise I don't see any reason why one should not be able to paste it as such anywhere in any other script the way it is written.

see also: The Top of the Script (the Auto-execute Section)

A_AhkUser
my scripts
tatagi
Posts: 181
Joined: 23 Aug 2018, 11:17

Re: Please help complete this script(confining mouse to a window)

01 Oct 2020, 08:46

@A_AhkUser

Unfortunately it's not. I removed it and still the same problem persists..

same error dialog "this line will never execute, due to return preceding it." occurs when running the script.

Not sure why. Tried #include to no avail either
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: Please help complete this script(confining mouse to a window)

01 Oct 2020, 09:13

@A_AhkUser the error is in assuming a particular default object property enumeration order. there isnt one, since its undocumented(there is but coding against the implementation is done so at ur own peril as it is subject to change)

tldr: hwxy
User avatar
Jim Dunn
Posts: 478
Joined: 01 Sep 2020, 20:21
Location: NSW

Re: Please help complete this script(confining mouse to a window)

01 Oct 2020, 09:22

swagfag wrote:
01 Oct 2020, 09:13
@A_AhkUser the error is in assuming a particular default object property enumeration order. there isnt one, since its undocumented(there is but coding against the implementation is done so at ur own peril as it is subject to change)

tldr: hwxy
You're quite probably absolutely correct, but, regardless of that:
tatagi wrote:
01 Oct 2020, 08:46
same error dialog "this line will never execute, due to return preceding it." occurs when running the script.
is still likely to be a separate, script structure issue, where tatagi is trying to paste the code after hotkeys or other returns which mean it will never get executed (or has moved other code into such a position while adding this) (per Structure of a Script) -
regardless of whether whether the added code would 'work' for tatagi, or not, isn't it? Because that error would, as far as I can guess, mean that tatagi is quite possibly never getting as far as executing the code to know if it 'works'?...

Perhaps I'm wrong, and the "this line will never execute, due to return preceding it." error can be triggered under other circumstances?

I guess we'd know more, and have to do much less guessing, if tatagi just told us exactly what "this line" was pointing at in the warning - or, ideally, we could see the whole script tatagi is trying to run, and verbatim, entire warning text which results. ;)
It's so hard, sometimes, when you just come to one of these threads and are only shown selected 'bits' because trying to replicate the errors to help diagnose them is often, then, so problematical...

I'm often dumb, so I'm probably missing something...
tatagi
Posts: 181
Joined: 23 Aug 2018, 11:17

Re: Please help complete this script(confining mouse to a window)

01 Oct 2020, 10:36

Ok guys, here's the complete script I am now using. and after I combined the script @A_AhkUser provided into mine, I got dozens of error msg when running the merged script. Please check this out and get back here..


Code: Select all

#NoEnv
#Warn
SendMode Input
SetWorkingDir %A_ScriptDir%
#SingleInstance force

winTitle := "ahk_class Notepad"
!x::ExitApp


OnActivate(hActivation:=-1) { ; https://docs.microsoft.com/en-us/windows/win32/menurc/using-cursors#confining-a-cursor
	local
	static rcOldClip := ""
	static hOldActivation := ""
	if (hActivation) {
		((hActivation <> -1) && hOldActivation:=hActivation)
		VarSetCapacity(rcOldClip, 16, 0) ; previous area for ClipCursor
		DllCall("User32.dll\GetClipCursor", "Ptr", &rcOldClip) ; Record the area in which the cursor can move.
		VarSetCapacity(rcClip, 16, 0) ; new area for ClipCursor
		DllCall("User32.dll\GetWindowRect", "Ptr", hOldActivation, "Ptr", &rcClip) ; Get the dimensions of the application's window.
		DllCall("User32.dll\ClipCursor", "Ptr", &rcClip) ; Confine the cursor to the application's window.
		SetTimer % A_ThisFunc, 100
	} else {
		SetTimer % A_ThisFunc, Off
		(rcOldClip && DllCall("User32.dll\ClipCursor", "Ptr", &rcOldClip), rcOldClip:="") ; Restore the cursor to its previous area.
	}
}
; =====================================
shellMessage(wParam, lParam) { ; based on https://autohotkey.com/board/topic/80644-how-to-hook-on-to-shell-to-receive-its-messages/
	local
	global winTitle
	static f := (Func("OnActivate")
			, DllCall("RegisterShellHookWindow", "Ptr", A_ScriptHwnd)
			, OnMessage(DllCall("RegisterWindowMessage", "Str", "SHELLHOOK"), "shellMessage")
			, OnExit("shellMessage"))
	static iRcOldClip := ""
	static _ := (VarSetCapacity(iRcOldClip, 16, 0) ; the very initial area for ClipCursor
			, DllCall("User32.dll\GetClipCursor", "Ptr", &iRcOldClip)) ; Record the initial area in which the cursor can move.
	Critical
	if (wParam = A_ExitReason) {
		return 0, DllCall("DeregisterShellHookWindow", "UInt", A_ScriptHwnd), DllCall("User32.dll\ClipCursor", "Ptr", &iRcOldClip) ; Restore the cursor to its very initial area. 
	}
	if ((wParam = 32772) or (wParam = 4)) { ; HSHELL_WINDOWACTIVATED := 4, HSHELL_RUDEAPPACTIVATED := 32772
		fn := f.bind(WinActive(winTitle))
		SetTimer % fn, -1
	}
}

;and here comes my script

setstorecapslockmode, off
setcapslockstate, off
#inputlevel 1
hotkey, e, off
hotkey, r, off
capslock::vkFF   ;remaps capslock into unassigned vkFF
#inputlevel 0   ;instead of "capslock & ..."  use "vkFF & ..."
vkFF & 0::   ;turns capslock on and off
setcapslockstate % !getkeystate("capslock", "t")
return

#maxhotkeysperinterval 200
#hotkeyinterval 100
setbatchlines, -1
setkeydelay, -1

vkFF & e::
sendInput {wheelup}
hotkey, e, on
settimer, block_e, 300
return

e::
return

block_e:
hotkey, e, off
settimer, block_e, off
return

vkFF & r::
sendInput {wheeldown}
hotkey, r, on
settimer, block_r, 300
return

r::
return

block_r:
hotkey, r, off
settimer, block_r, off
return

!up::soundset +2
return

!down::soundset -2
return

vkFF & a::
ifwinexist, ahk_class CabinetWClass
winclose
else
run c:\users\lovejoy\downloads, , max
return

vkFF & w::
run c:\users\lovejoy\downloads\type10.txt, , max
winwait, ahk_class Notepad
winactivate, ahk_class Notepad
return

vkFF & t::sendinput {volume_mute}
return

vkFF & y::
detecthiddenwindows on
settitlematchmode 2
ifwinexist, SafeVisit
winclose
else
run c:\users\lovejoy\downloads\safevisit\safevisit.exe, , hide
return

#ifwinactive, ahk_class CabinetWClass
~mbutton::send !{up}
return
#ifwinactive

#ifwinactive, ahk_class Chrome_WidgetWin_1
vkFF & enter::send !{enter}
return
#ifwinactive



IME_CHECK(WinTitle)
{
    WinGet,hWnd,ID,%WinTitle%
    Return Send_ImeControl(ImmGetDefaultIMEWnd(hWnd),0x005,"")
}
Send_ImeControl(DefaultIMEWnd, wParam, lParam)
{
    DetectSave := A_DetectHiddenWindows       
    DetectHiddenWindows,ON                           

     SendMessage 0x283, wParam,lParam,,ahk_id %DefaultIMEWnd%
    if (DetectSave <> A_DetectHiddenWindows)
        DetectHiddenWindows,%DetectSave%
    return ErrorLevel
}
ImmGetDefaultIMEWnd(hWnd)
{
    return DllCall("imm32\ImmGetDefaultIMEWnd", Uint,hWnd, Uint)
}

vkFF & o::
sleep 50
    ret := ime_check("a")
    if %ret% = 0               
    {
        send, {vk15}           
    }
return

vkFF & p::
sleep 50
    ret := ime_check("a")
    if %ret% <> 0           
    {
        send, {vk15}          
    }
return

vkFF & lbutton::
if a_cursor = ibeam
{
send, {click}^a
sleep 50
    ret := ime_check("a")
    if %ret% = 0
    {
        send, {vk15}
    }
}
else
{
send {lbutton}
}
return

vkFF & rbutton::
if a_cursor = ibeam
{
send, {click}^a
sleep 50
    ret := ime_check("a")
    if %ret% <> 0
    {
        send, {vk15}
    }
}
else
{
send {rbutton}
}
return
User avatar
Jim Dunn
Posts: 478
Joined: 01 Sep 2020, 20:21
Location: NSW

Re: Please help complete this script(confining mouse to a window)

01 Oct 2020, 10:51

Well, if I remove (apart from your standard opening stuff) up to:

;and here comes my script

The first error I get is:

Error at line 69.

Line Text: *capslock
Error: Duplicate hotkey.


Was this script actually working before you tried to add this new code?
tatagi
Posts: 181
Joined: 23 Aug 2018, 11:17

Re: Please help complete this script(confining mouse to a window)

01 Oct 2020, 11:02

@Jim Dunn


it's weird, I don't get any errors if Ahk_user's script is cut out. there's no duplicate hotkey I am 120% sure because I am using it right now.
User avatar
Jim Dunn
Posts: 478
Joined: 01 Sep 2020, 20:21
Location: NSW

Re: Please help complete this script(confining mouse to a window)

01 Oct 2020, 11:05

No, you're right, my error, sorry - I double pasted some stuff. Apologies for that. :oops:

For an easier comparison, could you please paste in two code boxes:

(1) What is working (your existing script which you say you are using now, before you tried to add this stuff) - which gives you no errors/warnings

(2) The exact version you revised that isn't working - which gives you lots of errors/warnings

In their entirety.

Thanks
Last edited by Jim Dunn on 01 Oct 2020, 11:20, edited 1 time in total.
tatagi
Posts: 181
Joined: 23 Aug 2018, 11:17

Re: Please help complete this script(confining mouse to a window)

01 Oct 2020, 11:18

Jim Dunn wrote:
01 Oct 2020, 11:05
No, you're right, my error, sorry - I double pasted some stuff. :oops:

For an easier comparison, could you please paste in two code boxes:

(1) What is working (your existing script before you tried to add this stuff)

(2) The exact version you revised that isn't working

In their entirety.

Thanks
(1) my original working script...

Code: Select all

setstorecapslockmode, off
setcapslockstate, off
#inputlevel 1
hotkey, e, off
hotkey, r, off
capslock::vkFF   ;remaps capslock into unassigned vkFF
#inputlevel 0   ;instead of "capslock & ..."  use "vkFF & ..."
vkFF & 0::   ;turns capslock on and off
setcapslockstate % !getkeystate("capslock", "t")
return

#maxhotkeysperinterval 200
#hotkeyinterval 100
setbatchlines, -1
setkeydelay, -1

vkFF & e::
sendInput {wheelup}
hotkey, e, on
settimer, block_e, 300
return

e::
return

block_e:
hotkey, e, off
settimer, block_e, off
return

vkFF & r::
sendInput {wheeldown}
hotkey, r, on
settimer, block_r, 300
return

r::
return

block_r:
hotkey, r, off
settimer, block_r, off
return

!up::soundset +2
return

!down::soundset -2
return

vkFF & a::
ifwinexist, ahk_class CabinetWClass
winclose
else
run c:\users\lovejoy\downloads, , max
return

vkFF & w::
run c:\users\lovejoy\downloads\type10.txt, , max
winwait, ahk_class Notepad
winactivate, ahk_class Notepad
return

vkFF & t::sendinput {volume_mute}
return

vkFF & y::
detecthiddenwindows on
settitlematchmode 2
ifwinexist, SafeVisit
winclose
else
run c:\users\lovejoy\downloads\safevisit\safevisit.exe, , hide
return

#ifwinactive, ahk_class CabinetWClass
~mbutton::send !{up}
return
#ifwinactive

#ifwinactive, ahk_class Chrome_WidgetWin_1
vkFF & enter::send !{enter}
return
#ifwinactive



IME_CHECK(WinTitle)
{
    WinGet,hWnd,ID,%WinTitle%
    Return Send_ImeControl(ImmGetDefaultIMEWnd(hWnd),0x005,"")
}
Send_ImeControl(DefaultIMEWnd, wParam, lParam)
{
    DetectSave := A_DetectHiddenWindows       
    DetectHiddenWindows,ON                           

     SendMessage 0x283, wParam,lParam,,ahk_id %DefaultIMEWnd%
    if (DetectSave <> A_DetectHiddenWindows)
        DetectHiddenWindows,%DetectSave%
    return ErrorLevel
}
ImmGetDefaultIMEWnd(hWnd)
{
    return DllCall("imm32\ImmGetDefaultIMEWnd", Uint,hWnd, Uint)
}

vkFF & o::
sleep 50
    ret := ime_check("a")
    if %ret% = 0               
    {
        send, {vk15}           
    }
return

vkFF & p::
sleep 50
    ret := ime_check("a")
    if %ret% <> 0           
    {
        send, {vk15}          
    }
return

vkFF & lbutton::
if a_cursor = ibeam
{
send, {click}^a
sleep 50
    ret := ime_check("a")
    if %ret% = 0
    {
        send, {vk15}
    }
}
else
{
send {lbutton}
}
return

vkFF & rbutton::
if a_cursor = ibeam
{
send, {click}^a
sleep 50
    ret := ime_check("a")
    if %ret% <> 0
    {
        send, {vk15}
    }
}
else
{
send {rbutton}
}
return
(2) the combined script that isn't working + error code

Code: Select all

#NoEnv
#Warn
SendMode Input
SetWorkingDir %A_ScriptDir%
#SingleInstance force

winTitle := "ahk_class Notepad"
!x::ExitApp


OnActivate(hActivation:=-1) { ; https://docs.microsoft.com/en-us/windows/win32/menurc/using-cursors#confining-a-cursor
	local
	static rcOldClip := ""
	static hOldActivation := ""
	if (hActivation) {
		((hActivation <> -1) && hOldActivation:=hActivation)
		VarSetCapacity(rcOldClip, 16, 0) ; previous area for ClipCursor
		DllCall("User32.dll\GetClipCursor", "Ptr", &rcOldClip) ; Record the area in which the cursor can move.
		VarSetCapacity(rcClip, 16, 0) ; new area for ClipCursor
		DllCall("User32.dll\GetWindowRect", "Ptr", hOldActivation, "Ptr", &rcClip) ; Get the dimensions of the application's window.
		DllCall("User32.dll\ClipCursor", "Ptr", &rcClip) ; Confine the cursor to the application's window.
		SetTimer % A_ThisFunc, 100
	} else {
		SetTimer % A_ThisFunc, Off
		(rcOldClip && DllCall("User32.dll\ClipCursor", "Ptr", &rcOldClip), rcOldClip:="") ; Restore the cursor to its previous area.
	}
}
; =====================================
shellMessage(wParam, lParam) { ; based on https://autohotkey.com/board/topic/80644-how-to-hook-on-to-shell-to-receive-its-messages/
	local
	global winTitle
	static f := (Func("OnActivate")
			, DllCall("RegisterShellHookWindow", "Ptr", A_ScriptHwnd)
			, OnMessage(DllCall("RegisterWindowMessage", "Str", "SHELLHOOK"), "shellMessage")
			, OnExit("shellMessage"))
	static iRcOldClip := ""
	static _ := (VarSetCapacity(iRcOldClip, 16, 0) ; the very initial area for ClipCursor
			, DllCall("User32.dll\GetClipCursor", "Ptr", &iRcOldClip)) ; Record the initial area in which the cursor can move.
	Critical
	if (wParam = A_ExitReason) {
		return 0, DllCall("DeregisterShellHookWindow", "UInt", A_ScriptHwnd), DllCall("User32.dll\ClipCursor", "Ptr", &iRcOldClip) ; Restore the cursor to its very initial area. 
	}
	if ((wParam = 32772) or (wParam = 4)) { ; HSHELL_WINDOWACTIVATED := 4, HSHELL_RUDEAPPACTIVATED := 32772
		fn := f.bind(WinActive(winTitle))
		SetTimer % fn, -1
	}
}

;and here comes my script

setstorecapslockmode, off
setcapslockstate, off
#inputlevel 1
hotkey, e, off
hotkey, r, off
capslock::vkFF   ;remaps capslock into unassigned vkFF
#inputlevel 0   ;instead of "capslock & ..."  use "vkFF & ..."
vkFF & 0::   ;turns capslock on and off
setcapslockstate % !getkeystate("capslock", "t")
return

#maxhotkeysperinterval 200
#hotkeyinterval 100
setbatchlines, -1
setkeydelay, -1

vkFF & e::
sendInput {wheelup}
hotkey, e, on
settimer, block_e, 300
return

e::
return

block_e:
hotkey, e, off
settimer, block_e, off
return

vkFF & r::
sendInput {wheeldown}
hotkey, r, on
settimer, block_r, 300
return

r::
return

block_r:
hotkey, r, off
settimer, block_r, off
return

!up::soundset +2
return

!down::soundset -2
return

vkFF & a::
ifwinexist, ahk_class CabinetWClass
winclose
else
run c:\users\lovejoy\downloads, , max
return

vkFF & w::
run c:\users\lovejoy\downloads\type10.txt, , max
winwait, ahk_class Notepad
winactivate, ahk_class Notepad
return

vkFF & t::sendinput {volume_mute}
return

vkFF & y::
detecthiddenwindows on
settitlematchmode 2
ifwinexist, SafeVisit
winclose
else
run c:\users\lovejoy\downloads\safevisit\safevisit.exe, , hide
return

#ifwinactive, ahk_class CabinetWClass
~mbutton::send !{up}
return
#ifwinactive

#ifwinactive, ahk_class Chrome_WidgetWin_1
vkFF & enter::send !{enter}
return
#ifwinactive



IME_CHECK(WinTitle)
{
    WinGet,hWnd,ID,%WinTitle%
    Return Send_ImeControl(ImmGetDefaultIMEWnd(hWnd),0x005,"")
}
Send_ImeControl(DefaultIMEWnd, wParam, lParam)
{
    DetectSave := A_DetectHiddenWindows       
    DetectHiddenWindows,ON                           

     SendMessage 0x283, wParam,lParam,,ahk_id %DefaultIMEWnd%
    if (DetectSave <> A_DetectHiddenWindows)
        DetectHiddenWindows,%DetectSave%
    return ErrorLevel
}
ImmGetDefaultIMEWnd(hWnd)
{
    return DllCall("imm32\ImmGetDefaultIMEWnd", Uint,hWnd, Uint)
}

vkFF & o::
sleep 50
    ret := ime_check("a")
    if %ret% = 0               
    {
        send, {vk15}           
    }
return

vkFF & p::
sleep 50
    ret := ime_check("a")
    if %ret% <> 0           
    {
        send, {vk15}          
    }
return

vkFF & lbutton::
if a_cursor = ibeam
{
send, {click}^a
sleep 50
    ret := ime_check("a")
    if %ret% = 0
    {
        send, {vk15}
    }
}
else
{
send {lbutton}
}
return

vkFF & rbutton::
if a_cursor = ibeam
{
send, {click}^a
sleep 50
    ret := ime_check("a")
    if %ret% <> 0
    {
        send, {vk15}
    }
}
else
{
send {rbutton}
}
return

it returns errors 7 times:

Warning: This line will never execute, due to Return preceeding it.

051: SetStoreCapslockMode,off
064: SetBatchLines,-1
096: Return
099: Return
115: Return
128: Return
133: Return
A_AhkUser
Posts: 1147
Joined: 06 Mar 2017, 16:18
Location: France
Contact:

Re: Please help complete this script(confining mouse to a window)

01 Oct 2020, 11:25

@Jim Dunn
Actaully, swagfag was refering to another "error" mentionned above [EDIT: fixed link] (admittely this was a ambiguous). Otherwise, you're right: the message of the real error indicates a script structure issue.

@tatagi
Disable warnings or rewrite your script so that the parser does not detect unreachable code.

In particular:
placing return after a single-line hotkey is redundant and will cause a warning.
source: #Warn

@swagfag
Oh I cannot believe I missed something so obvious :oops: ; off course, ahk keeps keys sorted... Thanks for your input ;)


A_AhkUser
my scripts
User avatar
Jim Dunn
Posts: 478
Joined: 01 Sep 2020, 20:21
Location: NSW

Re: Please help complete this script(confining mouse to a window)

01 Oct 2020, 11:33

... there was nothing useful in this post, so removing, to avoid confusion ...
Last edited by Jim Dunn on 01 Oct 2020, 12:06, edited 4 times in total.
tatagi
Posts: 181
Joined: 23 Aug 2018, 11:17

Re: Please help complete this script(confining mouse to a window)

01 Oct 2020, 11:43

@A_AhkUser
Disabling warnings does not solve anything actually. it just stops showing error code, while the script malfunctions or not function at all as far as errors are not revised. I removed all return for single line hotkey to see what happens, doesn't do a thing. and I can't remove setstorecapslockmode line because it's essential.

@Jim Dunn
trial & error is what I am doing, but nothing seems to take effect for a debug.
If all fails, I will probably have to run 2 separate scripts , the final cure-all haha

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: No registered users and 255 guests