AutoHotKey macro - difficulty with window focus - macros

PREVIOUS QUESTION:
I'm playing an online flash game that is basically Hangman. The only way to input letters is by clicking on them on the on-screen keyboard in the game.
I'd like to write some sort of macro that would map keyboard presses with mouse locations, so that I could type the letters on my keyboard and have the mouse go click on the corresponding on-screen keyboard letters.
I'm running Windows 7 on a Dell laptop. Is there any way to do this? Any programs that would help with this? I have some experience programming in Java if that helps.
UPDATE: I'm using AutoHotKey to write the macro.
Here is what I have:
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn ; Enable warnings to assist with detecting common errors.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
LAlt & a::
IfWinExist Bearville - Mozilla Firefox
{
WinActivate
}
DllCall("mouse_event", "UInt", 0x01, "UInt", 460, "UInt", 560) ; move
DllCall("mouse_event", "UInt", 0x02) ; left button down
DllCall("mouse_event", "UInt", 0x04) ; left button up
sleep 250
DllCall("mouse_event", "UInt", 0x01, "UInt", -460, "UInt", -560) ; move
return
LAlt & b::
IfWinExist Bearville - Mozilla Firefox
{
WinActivate
}
DllCall("mouse_event", "UInt", 0x01, "UInt", 500, "UInt", 560) ; move
DllCall("mouse_event", "UInt", 0x02) ; left button down
DllCall("mouse_event", "UInt", 0x04) ; left button up
sleep 250
DllCall("mouse_event", "UInt", 0x01, "UInt", -500, "UInt", -560) ; move
return
and so on. If the window is not active, activate it. Move the pointer from the upper left corner to the location of the letter on the screen, left mouse button down and up, wait 250 milliseconds (because having no delay resulted in the click not registering) and then move the pointer back to the starting location.
This works for one letter, but if I try to enter another letter right afterwards, the window loses focus as soon as I press the left alt key. Finishing entering the hotkey makes the window activate but the pointer does not seem to move or click, and the window loses focus again. How can I fix it?

If the virtual keyboard has a fixed position, you can use this...
a::MouseClick, left, 150,150
b::MouseClick, left, 250,250
Just use autoHotKey Window Spy to find the exact mouse coordinates. you will need to do this 26 times though, but it is easy and straight forward and should not cause any loss of focus problems.

If there is a reason you are using DllCalls instead of send, this might not work, but what I would do for this type of application is write a hotkey that starts a loop until another hotkey is pressed, and then use input to listen for any typed characters to click on.
Something like this:
LAlt & a::
IfWinExist Bearville - Mozilla Firefox
{
WinActivate
}
flag = 1
while flag
{
Input, inval, B L1, {Space}
IfInString, errorlevel, EndKey
{
flag = 0
} else {
x, y = locationForChar(inval)
;I'd reccomened a switch or if statement chain
Send {Click %x%, %y%}
}
}
This should start reading all input after the 'LAlt & a' hotkey is pressed, and will terminate after the space key is pressed.

Related

Hotkey doesn't loop with Send command

I have this code, and i want to whenever i hold ctrl+n it will click and drag. It doesn't loop with the Send commands in place. It only runs once, unless i let go of ctrl and n and press again. If i comment them out the hotkey loops perfectly fine when i hold it down. Heres my script:
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
#Warn ; Enable warnings to assist with detecting common errors.
; SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
^n::
CoordMode, Mouse, Screen
Send {LButton down} ;if i comment these two out it works fine
MouseMove, 0, 30, 20, R
Send {LButton up} ; ditto
return
The problem was ctrl key. When pressed down it stops new execution of hotkey. I tried it without ctrl prefix and used just n:: and it worked fine. It also works if you press ctrl+n then release it then press it again.
Anyways when you add Hotkey Modifier $ sign in front it works as you wanted.
Hotkey Modifier $ explanation:
This is usually only necessary if the script uses the Send command to send the keys that comprise the hotkey itself, which might otherwise cause it to trigger itself. The $ prefix forces the keyboard hook to be used to implement this hotkey, which as a side-effect prevents the Send command from triggering it. The $ prefix is equivalent to having specified #UseHook somewhere above the definition of this hotkey.
More info:
https://www.autohotkey.com/docs/Hotkeys.htm
$^n::
CoordMode, Mouse, Screen
Send {LButton down}
MouseMove, 0, 30, 20, R
Send {LButton up}
return

Send function key stroke from AutoHotkey to OBS Studio

I am trying to send a keystroke to OBS Studio using AutoHotkey.
The code I am using is
DetectHiddenWindows, On
hWnd := WinExist("ahk_exe obs64.exe")
ControlSend,, {F5}, ahk_id %hWnd%
The function I want to trigger is "start recording"
Nothing is delivered. There is a rumour that the latest OBS does not allow for ControlSend. Is that true? How do I circumvent that?
Use SetKeyDelay (or separate up & down events with delay in between) to make the key be held down for a bit longer.
;hold down for 50ms
SetKeyDelay, -1, 50
ControlSend, , {F5}, ahk_exe obs64.exe
Also, assuming you don't need the hwnd for something else, there's no need to get it.
And it should work just fine as well without detecting hidden windows.

AHK shortcuts for Alt+Space in Windows

running AHK in Windows 10, and I'm trying to create shortcuts for the Alt+Space menu. Specifically, I often use this sequence:
Press keys Alt+Space (bring up the window menu)
Press key S (select Size to resize)
Press key Left (now moving the mouse is resizing your window horizontally)
Press key Up (now moving the mouse is resizing your window in all directions)
Once this sequence is pressed, you can move your mouse to resize the active window as if you click-dragged the top-right corner, without having to hunt for that corner. (to finalize the resizing you can press Enter of LeftMouseKey, or Esc to abort). I'd like to get to this state with a single shortcut.
Here is my current script, binding to Winkey+Ctrl+Shift+1
;resize window from Top-Left
#^+1::
SendInput !{Space}
Sleep 100
SendInput s
Sleep 100
SendInput {Left}+{Up}
Return
It works mostly, but sometimes the active window will consume the s {Left} {Up} commands, rather than the popup menu. Thus, sometimes this shortcut will result in the active window like VSCode having the "s" character and the cursor 1 line up from before (as if typing s {Left} {Up}), and a visible Alt+Space menu.
I initially used Sleep 10 and thought Sleep 100 would fix this, but it didn't. The shortcut already feels slow with 2x Sleep 100 built in.
I'd like to test if the Alt+Space menu is open before SendInput s and preferably make sure I'm sending to the menu rather than the main application.
I was unable to reproduce the problem using your method. Perhaps try using Send, SendEvent, SendPlay, SendRaw, #InstallKeybdHook, #UseHook
Alternatively, use Autohotkey's WinMove statement:
This resizes the active window such that the upper left hand corner is at the current mouse position
#^+1::
CoordMode Mouse, screen
id := WinExist("A")
WinGetPos x, y, width, height, ahk_id %id%
MouseGetPos mx, my
neww := width + x - mx
newh := height + y - my
WinMove % "ahk_id" id,, mx, my, neww, newh
return
The menu itself is ahk_class #32768, so waiting for it to exist seems to work for me.
#^+1::
Send , !{space}
WinWait , ahk_class #32768 ,, 1 ; Waits 1s for menu to exist
If !ErrorLevel ; ErrorLevel is 0 if menu exists
Send , s{left}+{up}
Return
Jim U's alternative solution is a more reliable way of doing what you're trying to achieve, but this will make what you currently have work.

AutoHotKey: How to disable a Skype hotkey and make your keyboard behave normally

Skype HotKeys are really annoying as they cannot be disabled from Skype itself. The most annoying of all was Ctrl+R, that started a Skype call with any of your contact if it was selected. This has been replaced recently by Ctrl+Alt+R.
See http://community.skype.com/t5/Windows-desktop-client/Disable-CTRL-R-on-windows/td-p/2877763
Unfortunately, it happens to me that I get AltGr+R as a mapped key to the "è" character (using microsoft keybord creator). So in all my applications, I can write happily in French with a US keyboard, using AltGr+r for my "è" character all the time. Except in Skype, now.
Reading the link above, I created an AutoKey script, to disable Skype's hotkey:
#IfWinActive, ahk_exe Skype.exe ; utilizes this script for Skype only
!^r:: ; replace [ctrl][alt][r] with nothing
#If ; closes IfWinActive condition, needed if more code comes after this
But, although this disables the Skype hotkey, it prevents the normal input of my "è" character in a Skype discussion. So good, but not best, as my typing get all mangled in Skype now.
I have tried other options, but to no avail:
#IfWinActive, ahk_exe Skype.exe ; utilizes this script for Skype only
!^r::
Send è
return
#If ; closes IfWinActive condition, needed if more code comes after this
or
#IfWinActive, ahk_exe Skype.exe ; utilizes this script for Skype only
!^r::
SendInput {Raw}è
return
#If ; closes IfWinActive condition, needed if more code comes after this
But as soon as !^r is not strictly disabled, then it launched a Skype call.
Anyone with more experience with AutoHotKey and/or Skype to help me ?
Thanks.
You can avoid the whole problem if you assign the "unfortunate" hotkey combination to something else.
What I did:
Go to Tools->Options->Advanced->Hotkeys
Turn on "Enable keyboard shortcuts"
assign ctrl + alt + r to "Take a snapshot during video calls"
It was driving me crazy, I found the combined answer on skype forums.
Please note that this
#IfWinActive, ...
!^r::
#If
is no valid deactivation of a hotkey: attach the return keyword, so it is !^r::return. Otherwise, after pressing alt ctrl r, any code further down below will also be executed.
Also, if you only want to remap the AltGr hotkey, you should use <^>!r:: as the trigger, as suggested in the documentation. This way, the natural alt+ctrl+r behavior will be preserved, in this case making a call.
I cannot fully reproduce your issue.
#IfWinActive, ahk_exe Skype.exe
<^>!r::
send a
return
#ifWinActive
works perfectly fine for me and does not call my active contact in skype. AltGr is being overridden correctly. But if I change send a to send è, the script starts acting weirdly. It only works for the first time: after that, I have to press Alt manually once in order for è to be sent again. This looks like a bug to me.
A workaround might be
#IfWinActive, ahk_exe Skype.exe
<^>!r::
send è
keywait, alt
send {alt}
return
#ifWinActive
or
#IfWinActive, ahk_exe Skype.exe
<^>!r::
keywait, alt
send è
return
#ifWinActive
. But this still does not make it possible to send multiple è's while holding altGr down. You'll have to release AltGr after each è.
Edit - I found a 100% working solution:
#IfWinActive, ahk_exe Skype.exe
<^>!r::
SendUnicodeChar(0x00E8)
return
#ifWinActive
; SOURCE for the following: http://www.autohotkey.com/board/topic/16404-inserting-unicode-special-characters/
SendUnicodeChar(charCode)
{
VarSetCapacity(ki, 28 * 2, 0)
EncodeInteger(&ki + 0, 1)
EncodeInteger(&ki + 6, charCode)
EncodeInteger(&ki + 8, 4)
EncodeInteger(&ki +28, 1)
EncodeInteger(&ki +34, charCode)
EncodeInteger(&ki +36, 4|2)
DllCall("SendInput", "UInt", 2, "UInt", &ki, "Int", 28)
}
EncodeInteger(ref, val)
{
DllCall("ntdll\RtlFillMemoryUlong", "Uint", ref, "Uint", 4, "Uint", val)
}
this is the same as above, but instead of using send è or send {ASC 0232}, it uses unicode formatting.

Mouse Control with autohotkey

I'm making a script for 2 differents windows, and when I click on the first window, a click in the same position in the other window occurs.
The problem is, my script make the click but the x axis on the second window is always 0... and I don't know why
Maybe you got a solution or another way to script it?
This is my script:
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
#Warn ; Recommended for catching common errors.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
;retrouver les id de 2 fenetres
WinGet, first_id, ID, window1
WinGet, sec_id, ID, window2
;activation des fenetres
WinActivate, ahk_id %sec_id%
WinActivate, ahk_id %first_id%
; fonction pour quitter la macro
~Esc::ExitApp
return
;test repeter clic souris
;LeftClic
~LButton::
{
MouseGetPos, xposi, yposi
ControlClick, x%xposi% y%yposi%, ahk_id %first_id%,,LEFT
WinActivate, ahk_id %sec_id%
ControlClick, x%xposi% y%yposi%, ahk_id %sec_id%,,LEFT
WinActivate, ahk_id %first_id%
MouseMove, xposi, yposi
}
return
First and foremost, to quote the documentation for MouseGetPos:
The retrieved coordinates are relative to the active window unless
CoordMode was used to change to screen coordinates.
That means it's relative to the first window.
If these windows are not identical (in any case) the chances of this working for you are slim.
With that said, if they are identical you could change CoordMode to Screen and use WinMove to size and position the second window exactly as the first, after you activate it, and then just use the Click command.
The only other thing I can think of is looking at ControlClick's options, and you will see there is Xn and Yn, which is relative to a control. Every control is in fact a window, and sometimes an application only has one control, the main window.
Side-note: You wouldn't need curly brackets {} in your script.
They are only needed in a hotkey when you have a loop or a multi-line if / else block.