Use AutoHotkey to launch a game in an emulator - autohotkey

I want to create an .ahk script, that launches a game with an emulator. When the emulator is opened, it should send F10 to load a save state to get me directly to the game menu and jump the intros. This is what i got so far:
Run, C:\Users\****\Documents\!Others\Emulators\SNES9x\snes9x-x64.exe -fullscreen "E:\Consoles\Nintendo SNES\Goof Troop\Goof Troop.smc"
Sleep, 100
IfWinExist ahk_class Snes9X: WndClass
{
WinActivate
WinWaitActive
IfWinActive ahk_class Snes9X: WndClass
Send, {F10}
Return
}
I want to make sure that F10 is sent in the right time. The script should wait for the emulator to open first, am I doing it right?
Another thing that i have no idea on how to do, is to convert Xinput to Keyboard, for example when I am in-game and press LB + RB + B it converts it to ALT+F4 and closes the window, how can I do this?

The way i do is, suppose if the name of the emulator process is snes9x-x64.exe, then
processName := "snes9x-x64.exe"
run %processName%
flag = 0
Loop
{
WinGetTitle, title, ahk_exe %processName%
IfWinActive, %title%
{
If flag = 0
{
Send, {F10}
flag = 1
}
}
}
here once the emulator is opened we will check whether the window is active in a loop and then send F10 and stop the loop once the window is active using a flag.
And for the LB + RB + B, you will have to use a keyboard simulator like xpadder and map the keys LB,RB and B to keyboard keys and define a shortcut for that.

Related

How to hold a modifier key so ahk sends keypresses to a different window

I'm pretty new to ahk.
Say I have two separate vlc windows open and playing videos.
If one of the vlc windows is active, then I want to be able to hold a key to make all keypresses go to the other vlc window.
ie if I press Left, then it sends Left to the active vlc window, but if I hold ALT+Left, then it sends Left to the other vlc window.
If no vlc window is active, then I don't want autohotkey to do anything.
This is so I can control two vlc windows without having to click and choose which one is active.
I looked up GroupAdd hoping I could use a group that includes both vlc windows, but couldn't find a way to target specific vlc windows from the group to send keys to it.
edit: I got a very basic version working, but I feel it's pretty ugly. I would like a way to send any key that's pressed if you hold Shift to the other vlc window. Also this seems a bit unreliable in switching focus if you use it a few times quickly in succession.
GroupAdd, vlcgroup, ahk_exe vlc.exe
return
#IfWinActive ahk_exe vlc.exe
+Left:: ; shift-left
GroupActivate, vlcgroup, r
Send {Left}
GroupActivate, vlcgroup, r
return
A simple approach could be done like this:
#IfWinActive, ahk_exe vlc.exe
+Left::
WinGet, WindowList, List, ahk_exe vlc.exe
BottomMostVlcHwnd := WindowList%WindowList%
ControlSend, , {Left}, % "ahk_id " BottomMostVlcHwnd
return
^+Left::
WinGet, WindowList, List, ahk_exe vlc.exe
BottomMostVlcHwnd := WindowList%WindowList%
ControlSend, , ^{Left}, % "ahk_id " BottomMostVlcHwnd
return
...
#IfWinActive
You'd write out each hotkey.
WinGet, , List(docs) returns a legacy pseudo-array(docs) of hwnds to Vlc windows.
The last element in that array will be the bottom most window.
You can get the last element of a pseudo array via a dynamic variable trick WindowList%WindowList%.
Essentially you're accessing a variable named WindowListN, where N is the number for the last element in the pseudo-array.
Then ControlSend(docs) is used to send keys to the background window without the need to activate it.
And you refer to the background window by a window name like ahk_id 0x1234567(docs).
Of course writing out the hotkey for each key is pretty repetitive, so we can do something much better:
#IfWinActive, ahk_exe vlc.exe
+Left::
^+Left::
+Right::
^+Right::
+PgUp::
+PgDn::
WinGet, WindowList, List, ahk_exe vlc.exe
ControlSend, , % StrReplace(A_ThisHotkey, "+", "{") "}", % "ahk_id " WindowList%WindowList%
return
#IfWinActive
The hotkey definitions are just stacked on top of each other.
(If there were even more definitions, a loop with the Hotkey(docs) command could be nicer)
A_ThisHotkey(docs) will contain the hotkey that was used, and StrReplace(docs) is used to automatically replace the + with a {.
And finally the closing brace } is appended to the end.

autohotkey how to activate last opened window that changes its pid

I'm trying to setup a hotkey to always launch a new WindowsTerminal window and give it focus. Even if there is an existing window, I always want it to create a new window. I'm able to get the new window to run, but I'm having difficulty making it the Active window.
Capturing the pid during the Run command and using ahk_pid doesn't seem to work as the pid changes between launch and the active window that appears (msgbox debugging shows one pid, Window Spy shows a different pid). Using WinWait, ahk_exe WindowsTerminal.exe seems to return right away grabbing a pre-existing window.
#t::
Run, wt.exe, , , TermPid
;; TermPid seems to change between the launch and the final window that appears
WinWait, ahk_pid %TermPid%, , 3
if ErrorLevel {
MsgBox, WinWait timed out... %TermPid%
return
} else {
WinActivate
}
;; problems when there are other already existing WindowsTerminal.exe windows
;WinWait, ahk_exe WindowsTerminal.exe, , 3
;if ErrorLevel {
; MsgBox, WinWait timed out...
; return
;} else {
; WinActivate
;}
return
I tried to create before and after array containing the PIDs to determine which process was the newly created one, but targeting the last PID in the array created below seems to work as is.
Code:
#t::
Run, wt.exe
;If you are on a slow computer, you may need to increase this delay
Sleep 100 ;Forgot how to optimize this w/ WinWait, but not important rn bc its not critical
newArray:=[]
for proc in ComObjGet("winmgmts:").ExecQuery("Select * from Win32_Process"){
if(proc.Name=="WindowsTerminal.exe"){
prID := proc.ProcessId
newArray.Push(prID)
}
}
LastItem:=newArray[newArray.MaxIndex()]
WinActivate, ahk_pid %LastItem%
return

AutoHotKey - Run a program once send several times

I am pretty new to AutoHotkey, but I managed it to start my desired program and send an Enter-Key to it, but the probleme here is, the program should only start once and if started it should only receive that enter key, when I press the key stroke again and again it should only send that enter key.
And the program should should stay in the background and not focus after it receives the enter key.
My Code:
#n::
Run F:\V..c.exe
Send {enter}
return
Detect if the process exists and start the program minimized, then wait for its window to appear.
#n::
process, exist, PROGRAM.EXE
if (errorlevel = 0) {
run, d:\program.exe, , min
winwait, ahk_class PROGRAM_WINDOW_CLASS
}
controlSend, , {Enter}, ahk_class PROGRAM_WINDOW_CLASS
;or use the line below
;controlSend, ahk_parent, {Enter}, ahk_class PROGRAM_WINDOW_CLASS
return
Replace PROGRAM.EXE with the executable name of your program and PROGRAM_WINDOW_CLASS with the window class as seen in the Autohotkey Window Spy utility available in Start menu or in the folder of the Autohotkey (AU3_Spy.exe) or in the right click menu of the Autohotkey tray icon.
Instead of running the program minimized it's also possible to use SW_SHOWNOACTIVATE flag of shellExecute, so you can replace the run, d:\program,, min with this:
dllCall("shell32\ShellExecute", uint,0, uint,0, str,"d:\program.exe", uint,0, uint,0
,uint,SW_SHOWNOACTIVATE:=4)
you could try:
hasran := false
#n::
if (!hasran) {
Run F:\V..c.exe
hasran := true
}
Send {enter}
return
It wont check if that windows exists, but it will only run the program once. then you can navigate to that program and it will only hit the enter key. (if that program is not gui I dont think you can send key events to it)

Writing a Simple AutoHotkey Script (press a key every X second on desktop)

I need to press any useless key (like F11) every 5 minutes or less to keep the windows active (if it became inactive for 10 minutes it will lock-out).
But I need the key to be pressed on the desktop (so it doesn't effect any open windows).
I have tried
Loop
{
ControlSend, {F11}, WindowsApplication1
Sleep, 100000
}
but doesn't seem to work.
thanks.
edit: my current script:
#NoTrayIcon
NumLock::Run Calc.exe
PrintScreen::Run "C:\Windows\Sysnative\SnippingTool.exe"
; When I press Insert, I want to Show Desktop
Insert::Run, "%A_APPDATA%\Microsoft\Internet Explorer\Quick Launch\Shows Desktop.lnk"
; When I press Pause/ Break, I want to Lock the Computer
Pause::DllCall("LockWorkStation")
#IfWinActive, ahk_class CabinetWClass
~MButton::Send !{Up}
#IfWinActive
Return
Just move the cursor every X minutes:
#Persistent
SetTimer, MoveMouse
MoveMouse:
If ( A_TimeIdle > 300000 ) {
MouseMove, 1 , 1,, R
MouseMove, -1,-1,, R
}
Return
Code adopted from here.
This is definitely nothing that should require Autohotkey.
Just disable your screensaver.
Rightclick your desktop
Click Personalize (Vista/7/8) or Properties (XP)
Go to the screensaver options
Disable the screensaver
You might also wanna disable stuff like "turn off display after x minutes", "go to sleep after x minutes" and "turn of harddrives after x minutes".
You'll find that in the poweroptions. There is a button in the screensaver options to get there...
edit: Another way of disabling the screensaver using autohotkey would be the following script:
#Persistent
Menu, Tray, Icon, User32.dll, 4
Menu, Tray, Tip, Screen Saver Disabled !!!
OnExit, ScreenSaveActivate
DllCall("SystemParametersInfo", Int,17, Int,0, UInt,NULL, Int,2)
SetTimer, CheckScreenSaveActive, 999
Return
CheckScreenSaveActive:
DllCall("SystemParametersInfo", Int,16, UInt,NULL, "UInt *",SSACTIVE, Int,0)
If SSACTIVE
DllCall("SystemParametersInfo", Int,17, Int,0, UInt,NULL, Int,2)
Return
ScreenSaveActivate:
DllCall("SystemParametersInfo", Int,17, Int,1, UInt,NULL, Int,2)
ExitApp
Return
which was created by SKAN from the ahk forums.

Timer runs only once

Below script works fine.
It sends mouse clicks every 4 seconds
to KingSoft Writer.
But when I change the Timer length to -4000
instead of 4000 so that the timer will run only once
the script no longer works even once.
I am no longer able to send mouse clicks to
KingSoft Writer.
What am I doing wrong?
#Persistent
#SingleInstance
SetTimer, CheckApp, 4000
Return
CheckApp:
IfWinActive, ahk_class QWidget
{
sleep 2000
Click 486, 15
Click 570, 93
}
Return
Before I answer this question. Would you be so kind as to go back to the previous question and mark the answer you received there, by clicking on the WHITE check-mark to turn it GREEN.
I once tried the minus values and was not happy with the results, so I decided to always turn the timer off instead of using negative values.
#Persistent
#SingleInstance
SetTimer, CheckApp, 4000
Return
CheckApp:
IfWinActive, ahk_class QWidget
{
SetTimer, CheckApp, Off
Click 486, 15
Click 570, 93
}
Return
I removed your Sleep, 2000. Adding this sleep command blocks ahk 50% of the time (sleeping 50%) and adds nothing useful. It even makes the chance that another application steals the focus in those 2 seconds larger, so the mouse clicks could go to another application...
Do you have to use mouse clicks or can you use keyboard shortcuts. Mouse positions tend to be unreliable as menus move or expand/contract.
Update
#Persistent
#SingleInstance
Return ; Prevent the [Win]+w from executing on startup of script.
#w:: ; [Win]+w launches PolyEdit, waits for window and sends two mouse clicks.
Run, path to the PolyEdit window.exe
WinWaitActive, ahk_class QWidget
Sleep, 1000
Click 486, 15
Click 570, 93
Return
Now you can put the ahk script in the windows start menu and launch PolyEdit through [Win]+w (or any other key you define...)
Update 2
Not sure why you want to do this, because launching the app takes an action (clicking an icon or pressing a shortcut), which could be used to trigger the script. Now you have to constantly run checks in the background. You can create an icon that looks like KingSoft, but in reality is an ahk script.
But here you go!
#Persistent
#SingleInstance
SetTimer, CheckApp, 400
Return
InitiateKS := true
CheckApp:
IfWinExist, ahk_class QWidget
{
If InitiateKS
{
InitiateKS := false
WinActivate, ahk_class QWidget
TrayTip, KingSoft, Started, 1
;Click 486, 15
;Click 570, 93
}
}
Else ; if no KingSoft is running
{
InitiateKS := true
}
Return