AHK Branching KeyWaits in Middle of Hotkey - loops

I work in a doctors office doing billing. The programs made for this job are very basic and are absolutely riddled with bugs, so I repeat parts of my code a lot to make certain they work. I used two programs, one for the billing side, one for the chart. Right now, my hotkey grabs the date of birth and Medical Record Number of the patient from the billing side, goes to the chart side, searches for the patient based on those two things (normally the MRN would be sufficient, but Epic blows, so it's not enough) selects the patient, clicks "Chart Review," then waits for me to select a service date. Upon left click, it tabs back into the billing side so I can copy information to it. the issue is, sometimes the patient did not show up, and I have to record this. If they didn't show, there's no chart to click, and I have to click somewhere else to double check that they didn't show. I need a branching type of keywait where if I click, it tabs into the billing side, or if I hit A or something, it clicks appointments, and past, then tabs back to billing and clicks "Typed Notes". I can manage everything besides the branching part. Getkeystate statements don't seem to work, and I can't use an if statement with keywaits (apparently).
!D::
BlockInput, MouseMoveOff
sleep 100
Winactivate, Hyperspace
sleep 100
sendinput ^w
sleep 300
winactivate, Form billing
sleep 300
BlockInput, MouseMove
mouseclick,, 400, 70
BlockInput, MouseMove
click
sleep 200
sendinput ^c
sleep 400
dob:=Clipboard
sleep 400
BlockInput, MouseMove
mouseclick,, 385, 85
BlockInput, MouseMove
click
sleep 200
sendinput ^c
WinActivate, Hyperspace
sleep 400
sendinput ^3
sleep 400
sendinput ^v
sleep 400
BlockInput, MouseMove
mouseclick,, 200, 145
sleep 400
Clipboard:=dob
sleep 400
StringTrimLeft, dobyear, dob, 6
sleep 50
dobmathd:=A_YYYY-dobyear
sleep 50
StringTrimRight, dobmo, dob, 8
sleep 50
StringTrimRight, dobd, dob, 5
sleep 50
StringTrimLeft, dobday, dobd, 3
sleep 50
if (dobmo >= A_MM) and (dobday >= A_DD)
{
dobmathd--
}
sleep 50
sendinput ^v
sleep 200
sendinput {Enter}
sleep 200
sendinput {Enter}
sleep 1700
BlockInput, MouseMove
mouseclick,, 85, 235
sleep 300
BlockInput, MouseMoveOff
;if (character = a)
;{
;BlockInput, MouseMove
;mouseclick,, 325, 40
;sleep 200
;mouseclick,, 60, 285
;click
;sleep 400
;mouseclick,, 240, 435
;sleep 2000
;winactivate, Form billing
;BlockInput, MouseMoveOff
;return
;}
;if (
tooltip,%dobmathd% Years old, 415, 70
keywait, LButton, D, T200
sleep 200
winactivate, Form billing
return
The commented part was my last attempt, but I've been googling to find a real idea to try for a while. Any help is appreciated!
Edit: Maybe a "if I click here do this, or if I click here do this" kind of statement will work. I can get the dimensions of the Chart Review window vs the toolbar button for appointments. I've been experimenting with this for another task, but it might work here. Help with that would be appreciated too!
Edit:
#Bob, Actually, and sorry for the late reply, I found that looping a small statement with a few keywaits of very short lengths works well for me. I'll paste my code below.
And this is just a snippet, so it's not the full code.
SendInput, {Enter}
Sleep, 1800
BlockInput, MouseMove
MouseClick,, 85, 235
Sleep, 300
BlockInput, MouseMoveOff
Sleep, 20
Loop
{
KeyWait, LButton, D, T0.02 ;I've picked a chart, meaning they showed up for their appointment
If !ErrorLevel
{
Sleep, 400
BlockInput, MouseMoveOff
WinActivate, Form CMP
Return
}
KeyWait, Escape, D, T0.02
If !ErrorLevel
Return
KeyWait, ., D, T0.02 ;They do not appear to have shown up for their appointment, so check the appointment tab
If !ErrorLevel
{
BlockInput, MouseMove
MouseClick,, 315, 40
Sleep, 400
MouseClick,, 100, 285
Sleep, 1000
MouseClick,, 270, 440
Sleep, 300
BlockInput, MouseMoveOff
Loop
{
KeyWait, Y, D, T0.02 ;They did not show up for their appointment. Bill appropriately.
If !ErrorLevel
{
BlockInput, MouseMove
WinActivate, Form CMP
Sleep, 200
MouseClick,, 210, 260
Sleep, 200
MouseClick,, 100, 400
Sleep, 200
SendInput, No Show
Sleep, 200
WinActivate, Hyperspace
Sleep, 500
MouseClick,, 85, 235
Sleep 400
WinActivate, Form CMP
Sleep, 300
BlockInput, MouseMoveOff
Return
}
KeyWait, N, D, T0.02 ;Don't see a no show, re-check chart review.
If !ErrorLevel
{
BlockInput, MouseMove
MouseClick,, 85, 235
Sleep, 500
BlockInput, MouseMoveOff
KeyWait, LButton, D
Sleep, 400
WinActivate, Form CMP
BlockInput, MouseMoveOff
Return
}
KeyWait, Escape, D, T0.02
If !ErrorLevel
Return
}
}
}

I can't use an if statement with keywaits
There is a way to "abuse" Input command with L1 and V (might be good idea to throw in I as well) options to act as (somewhat limited) KeyWait replacement. That should work for your usage case.
(...)
Input,var,L1IV ; will act as KeyWait
if (var="a") {
foo:=Round(Sqrt(1764))
TrayTip,,The number is %foo%
}
else if (var="s")
MsgBox Sssnaaakess
(...)

Related

Autohotkey Button with loop

i have a question. I have create a few Buttons but when i start a button it dont start the loop. And how can i set a variable for a button that fits in %edelstein%
Thank you for help
#NoEnv
#SingleInstance Force
SetWorkingDir %A_ScriptDir%
SetBatchLines -1
^k::
Gui, Add, Button, x32 y29 w90 h40 , Diamand
Gui, Add, Button, x152 y29 w90 h40 , Flawless Diamand
Gui, Add, Button, x272 y29 w90 h40 , Perfekter Diamand
Gui, Show, w479 h379, Untitled GUI
InputBox, count,
Loop %count%
{
ImageSearch, found_x, found_y, 0, 0, 1200, 1200, *100 %edelstein%.png
if (!ErrorLevel)
{
Send, {Control down}
MouseClick, left, %found_x%, %found_y%
Send, {Control up}
}
I try it with different g Labels but it allways skip the Loop
Documentation is always your best friend.
#NoEnv
#SingleInstance, Force
SetWorkingDir, %A_ScriptDir%
SetBatchLines, -1
Gui, Add, Button, x32 y29 w90 h40 vDiamand gOnButtonClick, Diamand
Gui, Add, Button, x152 y29 w90 h40 vFlawless_Diamand gOnButtonClick, Flawless Diamand
Gui, Add, Button, x272 y29 w90 h40 vPerfekter_Diamand gOnButtonClick, Perfekter Diamand
Gui, Show, w479 h379, Untitled GUI
edelstein := "ImageName"
Return
GuiClose:
ExitApp
OnButtonClick:
Msgbox, % A_GuiControl
Return
^k::
InputBox, count
Loop, %count% {
ImageSearch, found_x, found_y, 0, 0, 1200, 1200, *100 %edelstein%.png
if (ErrorLevel = 2)
MsgBox, 16,, Could not conduct the search.
Else if (ErrorLevel = 1)
MsgBox, 16,, Icon could not be found on the screen.
Else {
Send, {Control down}
MouseClick, left, %found_x%, %found_y%
Send, {Control up}
}
}
Return

AHK How to make one SetTimer launch other, and than reversal

Goal of a code:
Timer CheckStart iterrates every 3 seconds until it find a choosen color.
If it finds pixel - it stops itself and start CheckStop timer, to look for another pixel every 3 seconds.
Rince and repeat
Also there is a keybind to check which timer was launched last.
#NoEnv
SendMode Input
checkstate = 0 ;just for checking state
SetTimer, CheckStart, 3000
Return
CheckStart:
PixelSearch, xx, zz, 710, 460, 730, 480, 0x385982, 0, Alt RGB
if !ErrorLevel {
checkstate = 1
SetTimer, CheckStart, Off
SetTimer, CheckEnd, 3000
Gosub, CheckEnd
}
Return
CheckEnd:
PixelSearch, xx, zz, 670, 160, 725, 200, 0xE60014, 0, Alt RGB
if !ErrorLevel {
checkstate = 0
SetTimer, CheckEnd, Off
SetTimer, CheckStart, 3000
Gosub, CheckStart
}
Return
^!z:: ; Control+Alt+Z
MouseGetPos, MouseX, MouseY
PixelGetColor, color, %MouseX%, %MouseY%, Alt RGB
MsgBox (checkstate%) colour: %color%.
return
What I'm getting:
Before i feed needed color to 1st timer, keybind works delayed, shows state only between iterrations. Can i make it async?
After i feed needed color to 1st timer, checker became "1", but CheckEnd timer not starting. (and so keybind start to work immediately)
What i'm doing wrong? or its just prohibited to launch timer by timer?
There is no such pixel search mode as Alt, that's only for PixelGetColor.
I'm going to assume the problem here is just the pixel search taking forever.
Add in the Fast mode.
So instead of Alt RGB try Fast RGB.

reboot in a click mouse loop not working

I am trying to reboot PC at specific hour when a click mouse loop is running. I used if + else conditions and when I try to run both pieces of code separately the script works but when put together only the mouse clicking loop is running while the timer process takes no effect. Any ideas what’s wrong?
^+f::
SetTimer, Chronos, 500
return
Chronos:
FormatTime, TimeToMeet,,HHmm
If (TimeToMeet = 2018)
{
Run, %comspec% /c shutdown -r -f -t 0
}
else
{
loop
{
MouseClick, Left, 787, 512, 1,0
Sleep 10000
}
}
Return
k::Pause
The loop statement never exits.
You're using a timer so I assume you want your code to be event driven. If that's the case, make the MouseClick part of a timer instead of a sleeping loop.
If you don't want to use events, put your shutdown clause inside of the loop
This clicks (787,512) every 10 seconds until 20:18, at which time it shuts the computer down
^+f::
SetTimer, Chronos, 500
return
Chronos:
loop
{
FormatTime, TimeToMeet,,HHmm
If (TimeToMeet = 2018)
{
Run, %comspec% /c shutdown -r -f -t 0
}
MouseClick, Left, 787, 512, 1,0
Sleep 10000
}
k::Pause
This clicks (787,512) every 10 seconds until 20:18, at which time it shuts the computer down
F2:: start()
F3:: stop()
start()
{
global running := 1
while running {
FormatTime TimeToMeet,,HHmm
if (TimeToMeet = 1349 )
Shutdown 13
click 787,512
sleep 10000
}
}
stop()
{
global running := 0
}

AutoHotkey - Script stops working after some time

I am having a problem with my script which stops working properly, roughly after every 20-30 minutes of running. The problem seems to be with the loop that i have constructed and it stopping after that specific time. It's not the entire script that stops working because for example when i press another bind on caps lock it behaves normally. Furthermore when reloading the autohotkey script i get a message that "The script could not be reloaded." which I have never experienced before this problem with the loop.
So here's the code:
#IfWinActive Tibia
SplashTextOn, 100, 40, Running, WASD
WinMove, Running,, 1, 21
;SUSPEND AND INFORMATION===================================================
CapsLock::
Suspend
Toggle := !Toggle
if (Toggle = 0)
SplashTextOn, 90, 25, Running, WASD
WinMove, Running,, 1, 27
if (Toggle = 1)
{
SplashTextOn, 120, 40, NOT RUNNING, TYPING
WinMove, NOT RUNNING,, 1497, 69
}
return
NumpadAdd::
MsgBox, You have 0.5 seconds to mouse over MAIN BACKPACK.
Sleep, 500
MouseGetPos, mainbpxpos, mainbpypos
MsgBox, You have 0.5 seconds to mouse over MAIN SLOT BACKPACK.
Sleep, 500
MouseGetPos, mainbpslotxpos, mainbpslotypos
MsgBox, You have 0.5 seconds to mouse over FOOD.
Sleep, 500
MouseGetPos, foodxpos, foodypos
MsgBox, You have 0.5 seconds to mouse over HAND.
Sleep, 500
MouseGetPos, handxpos, handypos
MsgBox, You have 0.5 seconds to mouse over BLANK on GROUND.
Sleep, 500
MouseGetPos, blankgroundxpos, blankgroundypos
MsgBox, You have 0.5 seconds to mouse over LAST BLANK.
Sleep, 500
MouseGetPos, lastblankxpos, lastblankypos
MsgBox, You have 0.5 seconds to mouse over MADE RUNES POS.
Sleep, 500
MouseGetPos, maderunesxpos, maderunesypos
MsgBox, You have 0.5 seconds to mouse over RUNBACK POSITION (OUT HOUSE).
Sleep, 500
MouseGetPos, runbackxpos, runbackypos
MsgBox, You have 0.5 seconds to mouse over RUN POSITION (IN HOUSE).
Sleep, 500
MouseGetPos, runxpos, runypos
InputBox, blankrunesleft, Blank runes left, Enter the blank runes left, , 200, 170
MsgBox, SCRIPT IS ABOUT TO RUN, CLOSE ALL BPS!
BreakLoop = 0
iamout = 0
enemy = 0
Loop
{
if (BreakLoop = 1) {
break
}
Loop, %blankrunesleft%
{
if (BreakLoop = 1) {
break
}
SetMouseDelay, 5
battleOne := ReadMemory(0x5C6950,"Tibia")
;Notify(battleOne)
if (battleOne > 0) {
MouseClick, left, runxpos, runypos
Sleep, 30000
MouseClickDrag, left, mainbpslotxpos, mainbpslotypos, blankgroundxpos, blankgroundypos
Sleep, 400
Send, {Control Down}g{Control Up}
Sleep, 200
Send, {Enter}
Sleep, 5000
iamout = 0
}
if (battleOne == 0) {
if (iamout == 0) {
MouseClick, right, mainbpxpos, mainbpypos
Sleep, 200
MouseClick, right, blankgroundxpos, blankgroundypos
Sleep, 200
MouseClickDrag, left, blankgroundxpos, blankgroundypos, mainbpslotxpos, mainbpslotypos
Sleep, 200
MouseClick, left, runbackxpos, runbackypos
iamout = 1
Sleep, 500
}
}
mana := ReadMemory(0x5C682C,"Tibia")
if (iamout == 1) {
if (mana > 999) {
MouseClick, right, foodxpos, foodypos
Sleep, 60
MouseClick, right, foodxpos, foodypos
Sleep, 60
MouseClick, right, foodxpos, foodypos
Sleep, 100
MouseClickDrag, left, lastblankxpos, lastblankypos, handxpos, handypos
Sleep, 350
Send, Adori Vita Vis
Sleep, 100
Send, {Enter}
Sleep, 500
MouseClickDrag, left, handxpos, handypos, lastblankxpos, lastblankypos
Sleep, 350
blankrunesleft -= 1
}
}
if (iamout == 1) {
if (blankrunesleft == 0) {
Sleep, 100
MouseClick, left, runxpos, runypos
Sleep, 2000
MouseClickDrag, left, mainbpslotxpos, mainbpslotypos, maderunesxpos, maderunesypos
Sleep, 400
MouseClick, right, mainbpxpos, mainbpypos
Sleep, 500
blankrunesleft = 20
iamout = 0
}
}
}
}
Esc::
BreakLoop = 1
return
#IfWinActive
Edit: To add up, I have restarted the pc and done 2 more tests on this script. The result was that it always stops running properly, after exactly 22 minutes. I have no idea what could be causing this, would appreciate any help
Maybe if you rearranged things a little bit.
Move this to the top with your other hotkey routines; hotkeys should always be at the top of your script.
Esc::
BreakLoop = 1
return
put a return after the last {
This will keep the script from exiting when the loop ends.
As to your stopping every 22 minutes - is it possible that this is the length of the loop sequence? Since the timing seems consistent, you ought to be able to find the issue by keeping an eye out for simultaneous events.
Also, so can you tell what line the script is on when it says it won't reload? If you right-click on the tray icon and choose "Open" you will be able to see the status of the lines being processed.
That sort of debuggin method also shows you the time each line took to process and run. That may be very valuable in your case.

AHK script for a timed autofire function

Goal of the script: to continually press Numpad0 for 10 seconds each time hotkey is pressed.
Current code:
toggle = 0
#MaxThreadsPerHotkey 2
timerToggle:
Toggle := !Toggle
sleep 10000
Toggle := !Toggle
F12::
SetTimer, timerToggle, -1
While Toggle{
send {NumPad0}
sleep 100
}
return
At present, the script will run as intended, but only once. Attempting to run it again after the first time does nothing. What am I missing?
I would rather use SetTimers instead of a 10 sec. long while like so
F12::
Send {Numpad0}
SetTimer, start, 100
SetTimer, stop, -10000
return
start:
Send {Numpad0}
return
stop:
SetTimer, start, off
return
Your script likely doesn't toggle your variable correctly. Here is a cleaner version of what you are trying to do which uses A_TickCount:
F12::SetTimer, HoldNumPad, -1
HoldNumPad:
kDown := A_TickCount
While ((A_TickCount - kDown) < 10000)
{
Send {Numpad0}
Sleep 100
}
Return
Note that pressing F12 while the label is running will not have any affect.
EDIT: Made SetTimer use -1 period to run only once, thanks to MCL.

Resources