Back to AutoHotkey Tools

RadMode Tools

v22.27-BV automation scripts and utilities for radiology workflows

How to Use

Complete AutoHotkey v2 script for radiology workflow automation

  1. 1Download the RadMode.ahk script and RadMode.exe runner, then place them in the same folder. Double-click the Runner (.exe) to launch — a setup GUI window will appear.
  2. 2Configure your hotkeys and settings in the setup GUI. The launcher minimizes to the system tray after setup — close it to stop the script.
  3. 3Press Caps + F to enter Rads Mode and Caps + D to exit. Dictation shortcuts and number hotkeys (1–5) are active only when Rads Mode is enabled.
  4. 4Press Caps + W to restore a previously saved workspace layout and Caps + C to refresh the PowerScribe target.
  5. 5Press Alt + Z for Break Glass.
  6. 6Press Ctrl + Alt + S to save workspace layout.
  7. 7Press Alt + P for site login and Alt + B for Bellevue remote desktop login.

Quick Reference

Key shortcuts — full list available in the script GUI

Global Shortcuts

Caps LockTrackball Scroll (Hold)
Alt + PLogin site
Alt + BLogin Bellevue RDP
Alt + ZBreak Glass
Ctrl + Alt + SSave workspace layout
Caps + FEnable Rads Mode
Caps + DExit Rads Mode
Caps + WRestore workspace layout
Caps + CRefresh PS target
Shift + CapsToggle CapsLock

Rads Mode — Dictation

DToggle dictation
HSave draft (F9)
FNext field
GPrevious field
SBackspace
ANew line
QClose window (Ctrl+W)

Mouse & Pick Lists

RLeft click
EMiddle click
WRight click
1–5Pick list in PowerScribe / type digit elsewhere

Visage viewer:

Z, X, C, VSend to Visage

Download Files

Both files are required — place them in the same folder

AutoHotkey Script
.ahk
RadMode.ahk
Download Script
Executable Runner
.exe
RadMode.exe
Download Runner
Full RadMode Automation Script
View the complete source code or copy it to your clipboard
1#Requires Autohotkey v2
2#SingleInstance Force
3CoordMode "ToolTip", "Screen"
4CoordMode "Mouse", "Screen" 
5CoordMode "Pixel", "Screen" 
6SetTitleMatchMode 2
7
8; ==============================================================================
9; Version & Configuration Defaults
10; Author: Ryan Cummings
11; ==============================================================================
12global VERSION := "v22.27-BV" ; Bare Number Picklists
13global INI_FILE := "rad_helper_settings.ini"
14
15; --- User Variables (Runtime) ---
16global USER := ""
17global PASS := ""
18global BV_PASS := ""
19global KEEPAWAKE := 0
20global TRACKBALL_SCROLL := 1
21global DEBUG_MODE := 0
22
23; --- Advanced Settings (Loaded from INI) ---
24global BTG_TAB_DELAY := 80        
25global BTG_POPUP_DELAY := 500     
26global SCROLL_THRESHOLD := 15     
27global SCROLL_LOCK_RATIO := 2.0   
28
29; --- Marker Customization ---
30global MARKER_SIZE := 5           
31global MARKER_COLOR := "FF0000"   
32global MARKER_ALPHA := 180        
33
34; --- Reliability Settings ---
35SetKeyDelay 10, 10
36global LOGIN_STEP_DELAY := 150    
37
38; --- Window Titles & Layout Apps ---
39global EPIC_TITLE := "Prod"
40global PS := "PowerScribe"
41global VISAGE := "Visage"
42global VISAGE_LOGIN := "Client Login ahk_class Qt51510QWindowIcon"
43
44global WORKSPACE_APPS := [
45    {name: "PowerScribe", disp: "PowerScribe", title: "360 ahk_exe Nuance.PowerScribe360.exe", enabled: 1},
46    {name: "Epic", disp: "Epic", title: "Epic ahk_exe wfica32.exe", enabled: 1},
47    {name: "VisageBrowser", disp: "Vis Browser", title: "Study Browser", enabled: 1},
48    {name: "VisageNavigator", disp: "Vis Nav", title: "Study Navigator", enabled: 1},
49    {name: "Chrome", disp: "Chrome", title: "ahk_exe chrome.exe", enabled: 1},
50    {name: "VisageWorklist", disp: "Vis Worklist", title: "Worklist", enabled: 1}
51]
52
53global RADSMODE := false
54global MarkerGui := unset
55
56; ==============================================================================
57; Initialization
58; ==============================================================================
59LoadSettings() 
60CreateCursorMarker()
61
62; ==============================================================================
63; Main GUI
64; ==============================================================================
65myGui := Gui()
66myGui.Title := "Radiology Helper " . VERSION
67myGui.BackColor := "FBFBFB"
68myGui.SetFont("s10", "Segoe UI")
69
70; --- Login Section ---
71myGui.Add("GroupBox", "x20 y10 w460 h115", "Login Credentials")
72
73myGui.Add("Text", "x40 y35 w70 h25 +0x200", "Username:")
74Edit1 := myGui.Add("Edit", "x115 y35 w130 h25", USER)
75myGui.Add("Text", "x255 y35 w70 h25 +0x200", "Password:")
76Edit2 := myGui.Add("Edit", "x330 y35 w110 h25 +Password", PASS)
77
78myGui.Add("Text", "x40 y75 w70 h25 +0x200", "BV Pass:")
79Edit3 := myGui.Add("Edit", "x115 y75 w130 h25 +Password", BV_PASS)
80
81; --- Action Button ---
82LaunchButton := myGui.Add("Button", "x20 y140 w260 h50 +Default", "Launch Visage System")
83LaunchButton.OnEvent("Click", LaunchButtonHandler)
84LaunchButton.SetFont("s11 bold")
85
86; --- Config Button ---
87ConfigButton := myGui.Add("Button", "x290 y140 w190 h50", "Advanced Config")
88ConfigButton.OnEvent("Click", OpenConfigMenu)
89
90; --- Options Section ---
91CheckBox1 := myGui.Add("CheckBox", "x40 y200 w150 h25 Checked" . KEEPAWAKE, "Prevent Sleep")
92CheckBox2 := myGui.Add("CheckBox", "x220 y200 w240 h25 Checked" . TRACKBALL_SCROLL, "Hold CapsLock to scroll")
93CheckBox3 := myGui.Add("CheckBox", "x40 y225 w150 h25 Checked" . DEBUG_MODE, "Debug Mode")
94
95CheckBox1.OnEvent("Click", UpdateGlobals)
96CheckBox2.OnEvent("Click", UpdateGlobals)
97CheckBox3.OnEvent("Click", UpdateGlobals)
98
99; --- Workspace Layout Section ---
100myGui.Add("GroupBox", "x20 y260 w460 h120", "Workspace Layout (Multi-Monitor)")
101
102Chk_PS := myGui.Add("CheckBox", "x30 y285 w140 h20 Checked" . WORKSPACE_APPS[1].enabled, "PowerScribe")
103Chk_Epic := myGui.Add("CheckBox", "x180 y285 w130 h20 Checked" . WORKSPACE_APPS[2].enabled, "Epic")
104Chk_VisB := myGui.Add("CheckBox", "x320 y285 w140 h20 Checked" . WORKSPACE_APPS[3].enabled, "Vis Browser")
105
106Chk_VisN := myGui.Add("CheckBox", "x30 y315 w140 h20 Checked" . WORKSPACE_APPS[4].enabled, "Vis Nav")
107Chk_Chrome := myGui.Add("CheckBox", "x180 y315 w130 h20 Checked" . WORKSPACE_APPS[5].enabled, "Chrome")
108Chk_VisW := myGui.Add("CheckBox", "x320 y315 w140 h20 Checked" . WORKSPACE_APPS[6].enabled, "Vis Worklist")
109
110Btn_SaveLayout := myGui.Add("Button", "x120 y345 w100 h25", "Save Layout")
111Btn_RestLayout := myGui.Add("Button", "x240 y345 w100 h25", "Restore Layout")
112
113; Link GUI controls to the array for dynamic text updates
114WORKSPACE_APPS[1].ctrl := Chk_PS
115WORKSPACE_APPS[2].ctrl := Chk_Epic
116WORKSPACE_APPS[3].ctrl := Chk_VisB
117WORKSPACE_APPS[4].ctrl := Chk_VisN
118WORKSPACE_APPS[5].ctrl := Chk_Chrome
119WORKSPACE_APPS[6].ctrl := Chk_VisW
120
121Chk_PS.OnEvent("Click", UpdateLayoutGlobals)
122Chk_Epic.OnEvent("Click", UpdateLayoutGlobals)
123Chk_VisB.OnEvent("Click", UpdateLayoutGlobals)
124Chk_VisN.OnEvent("Click", UpdateLayoutGlobals)
125Chk_Chrome.OnEvent("Click", UpdateLayoutGlobals)
126Chk_VisW.OnEvent("Click", UpdateLayoutGlobals)
127Btn_SaveLayout.OnEvent("Click", SaveWorkspace)
128Btn_RestLayout.OnEvent("Click", RestoreWorkspace)
129
130; --- Divider ---
131myGui.Add("Text", "x20 y390 w460 h2 0x10")
132
133; --- Reference Guide ---
134myGui.SetFont("s9", "Segoe UI")
135RefGroup := myGui.Add("GroupBox", "x20 y400 w460 h235", "Quick Reference Guide")
136
137; Column 1: Global
138myGui.SetFont("s9 w700")
139myGui.Add("Text", "x40 y420 w180", "Global Shortcuts")
140myGui.SetFont("s9 w400")
141myGui.Add("Text", "x40 y440 w200", "Caps + f : Rads Mode ON")
142myGui.Add("Text", "x40 y460 w200", "Caps + d : Rads Mode OFF")
143myGui.Add("Text", "x40 y480 w200", "Caps + w : Restore Layout")
144myGui.Add("Text", "x40 y500 w200", "Caps + c : Refresh PS Target")
145myGui.Add("Text", "x40 y520 w200", "Ctrl + Alt + s : Save Layout")
146myGui.Add("Text", "x40 y540 w200", "Alt + z : Fast Break Glass")
147myGui.Add("Text", "x40 y560 w200", "Shift + Caps : Toggle CapsLock")
148
149; Column 2: Rads Mode
150myGui.SetFont("s9 w700")
151myGui.Add("Text", "x260 y420 w180", "Rads Mode (Vim-Style)")
152myGui.SetFont("s9 w400")
153myGui.Add("Text", "x260 y440 w200", "d : Toggle Dictation")
154myGui.Add("Text", "x260 y460 w200", "h : Save Draft (F9)")
155myGui.Add("Text", "x260 y480 w200", "f / g : Next / Prev Field")
156myGui.Add("Text", "x260 y500 w200", "s / a : Backspace / Enter")
157myGui.Add("Text", "x260 y520 w200", "1 - 5 : Pick List Choice") 
158
159; Logic Note
160myGui.SetFont("s8 italic c555555")
161myGui.Add("Text", "x40 y590 w420", "Logic Note: Logins utilize a clipboard-injection method to instantly paste credentials, bypassing standard keystroke lag.")
162
163; Footer
164myGui.SetFont("s8 c777777")
165myGui.Add("Text", "x20 y640 w460 Center", "Note: Red dot indicator appears when Rads Mode is active.")
166
167UpdateLayoutDetection() ; Set initial UI state
168myGui.Show("w500 h670")
169
170; ==============================================================================
171; Cursor Marker Logic
172; ==============================================================================
173CreateCursorMarker() {
174    global MarkerGui, MARKER_SIZE, MARKER_COLOR, MARKER_ALPHA
175    if IsSet(MarkerGui)
176        MarkerGui.Destroy()
177    MarkerGui := Gui("+AlwaysOnTop -Caption +ToolWindow +E0x20") 
178    MarkerGui.BackColor := MARKER_COLOR
179    D := MARKER_SIZE
180    WinSetRegion("0-0 W" D " H" D " R" D "-" D, MarkerGui.Hwnd)
181    MarkerGui.Opt("+LastFound")
182    WinSetTransparent(MARKER_ALPHA, MarkerGui.Hwnd)
183}
184
185UpdateMarkerPos() {
186    global RADSMODE, MarkerGui, MARKER_SIZE
187    if (RADSMODE) {
188        MouseGetPos(&mX, &mY)
189        MarkerGui.Show("x" (mX + 12) " y" (mY + 12) " w" MARKER_SIZE " h" MARKER_SIZE " NoActivate")
190    } else {
191        MarkerGui.Hide()
192    }
193}
194
195; ==============================================================================
196; Advanced Config Menu
197; ==============================================================================
198OpenConfigMenu(*) {
199    advGui := Gui()
200    advGui.Title := "Advanced Configuration"
201    advGui.SetFont("s9", "Segoe UI")
202
203    advGui.Add("GroupBox", "x10 y10 w380 h100", "Rads Mode Indicator (Dot)")
204    advGui.Add("Text", "x30 y35 w100 h20", "Dot Size (px):")
205    Ctrl_Size := advGui.Add("Edit", "x130 y32 w60 h20 Number", MARKER_SIZE)
206    advGui.Add("Text", "x210 y35 w80 h20", "Hex Color:")
207    Ctrl_Color := advGui.Add("Edit", "x290 y32 w80 h20", MARKER_COLOR)
208    advGui.Add("Text", "x30 y65 w100 h20", "Opacity (0-255):")
209    Ctrl_Alpha := advGui.Add("Edit", "x130 y62 w60 h20 Number", MARKER_ALPHA)
210
211    advGui.Add("GroupBox", "x10 y120 w380 h130", "Workflow Settings")
212    advGui.Add("Text", "x30 y145 w150 h20", "Tab Delay (ms):")
213    Ctrl_TabDelay := advGui.Add("Edit", "x240 y142 w80 h20 Number", BTG_TAB_DELAY)
214    advGui.Add("Text", "x30 y175 w150 h20", "Scroll Sensitivity:")
215    Ctrl_Sens := advGui.Add("Edit", "x240 y172 w80 h20 Number", SCROLL_THRESHOLD)
216    advGui.Add("Text", "x30 y205 w150 h20", "Axis Lock Ratio:")
217    Ctrl_Lock := advGui.Add("Edit", "x240 y202 w80 h20", SCROLL_LOCK_RATIO)
218
219    SaveBtn := advGui.Add("Button", "x90 y270 w100 h30", "Save")
220    CancelBtn := advGui.Add("Button", "x200 y270 w100 h30", "Cancel")
221    SaveBtn.OnEvent("Click", SaveHandler)
222    CancelBtn.OnEvent("Click", (*) => advGui.Destroy())
223    advGui.Show()
224
225    SaveHandler(*) {
226        global BTG_TAB_DELAY, SCROLL_THRESHOLD, SCROLL_LOCK_RATIO
227        global MARKER_SIZE, MARKER_COLOR, MARKER_ALPHA
228        MARKER_SIZE := Ctrl_Size.Value
229        MARKER_COLOR := Ctrl_Color.Value
230        MARKER_ALPHA := Ctrl_Alpha.Value
231        BTG_TAB_DELAY := Ctrl_TabDelay.Value
232        SCROLL_THRESHOLD := Ctrl_Sens.Value
233        SCROLL_LOCK_RATIO := Number(Ctrl_Lock.Value) 
234        SaveSettings() 
235        CreateCursorMarker()
236        advGui.Destroy()
237        MsgBox("Settings Saved!", "Configuration", "Iconi T1")
238    }
239}
240
241; ==============================================================================
242; INI Persistence Functions
243; ==============================================================================
244LoadSettings() {
245    global BTG_TAB_DELAY, SCROLL_THRESHOLD, SCROLL_LOCK_RATIO
246    global MARKER_SIZE, MARKER_COLOR, MARKER_ALPHA, WORKSPACE_APPS
247    if FileExist(INI_FILE) {
248        try {
249            BTG_TAB_DELAY := IniRead(INI_FILE, "Citrix", "TabDelay", 80)
250            SCROLL_THRESHOLD := IniRead(INI_FILE, "Physics", "Sensitivity", 15)
251            SCROLL_LOCK_RATIO := IniRead(INI_FILE, "Physics", "AxisLock", 2.0)
252            MARKER_SIZE := IniRead(INI_FILE, "Marker", "Size", 5)
253            MARKER_COLOR := IniRead(INI_FILE, "Marker", "Color", "FF0000")
254            MARKER_ALPHA := IniRead(INI_FILE, "Marker", "Alpha", 180)
255            
256            for app in WORKSPACE_APPS {
257                app.enabled := IniRead(INI_FILE, "LayoutSettings", app.name . "_Enabled", 1)
258            }
259        }
260    }
261}
262
263SaveSettings() {
264    global WORKSPACE_APPS
265    IniWrite(BTG_TAB_DELAY, INI_FILE, "Citrix", "TabDelay")
266    IniWrite(SCROLL_THRESHOLD, INI_FILE, "Physics", "Sensitivity")
267    IniWrite(SCROLL_LOCK_RATIO, INI_FILE, "Physics", "AxisLock")
268    IniWrite(MARKER_SIZE, INI_FILE, "Marker", "Size")
269    IniWrite(MARKER_COLOR, INI_FILE, "Marker", "Color")
270    IniWrite(MARKER_ALPHA, INI_FILE, "Marker", "Alpha")
271    
272    for app in WORKSPACE_APPS {
273        IniWrite(app.enabled, INI_FILE, "LayoutSettings", app.name . "_Enabled")
274    }
275}
276
277; ==============================================================================
278; GUI Handlers & Detection
279; ==============================================================================
280UpdateGlobals(*) {
281    global USER := Edit1.Value, PASS := Edit2.Value, BV_PASS := Edit3.Value
282    global KEEPAWAKE := CheckBox1.Value
283    global TRACKBALL_SCROLL := CheckBox2.Value, DEBUG_MODE := CheckBox3.Value
284}
285
286UpdateLayoutGlobals(*) {
287    global WORKSPACE_APPS
288    WORKSPACE_APPS[1].enabled := Chk_PS.Value
289    WORKSPACE_APPS[2].enabled := Chk_Epic.Value
290    WORKSPACE_APPS[3].enabled := Chk_VisB.Value
291    WORKSPACE_APPS[4].enabled := Chk_VisN.Value
292    WORKSPACE_APPS[5].enabled := Chk_Chrome.Value
293    WORKSPACE_APPS[6].enabled := Chk_VisW.Value
294    SaveSettings()
295}
296
297UpdateLayoutDetection() {
298    global WORKSPACE_APPS
299    for app in WORKSPACE_APPS {
300        if WinExist(app.title) {
301            if !InStr(app.ctrl.Text, "(Active)")
302                app.ctrl.Text := app.disp . " (Active)"
303        } else {
304            if !InStr(app.ctrl.Text, "(Off)")
305                app.ctrl.Text := app.disp . " (Off)"
306        }
307    }
308}
309
310LaunchButtonHandler(*) {
311    LaunchVisage()
312    myGui.Minimize()
313}
314CloseHandler(*) => ExitApp()
315
316; ==============================================================================
317; Workspace Layout Core Logic
318; ==============================================================================
319SaveWorkspace(*) {
320    global INI_FILE, WORKSPACE_APPS
321    savedList := ""
322
323    for app in WORKSPACE_APPS {
324        if (app.enabled && WinExist(app.title)) {
325            minMax := WinGetMinMax(app.title)
326            
327            if (minMax == -1) {
328                WinRestore(app.title)
329                Sleep(50)
330            }
331
332            WinGetPos(&X, &Y, &W, &H, app.title)
333
334            IniWrite(X, INI_FILE, "Layout_" . app.name, "X")
335            IniWrite(Y, INI_FILE, "Layout_" . app.name, "Y")
336            IniWrite(W, INI_FILE, "Layout_" . app.name, "W")
337            IniWrite(H, INI_FILE, "Layout_" . app.name, "H")
338            IniWrite(minMax == 1 ? 1 : 0, INI_FILE, "Layout_" . app.name, "Maximized")
339
340            if (minMax == -1) {
341                WinMinimize(app.title)
342            }
343            savedList .= app.disp . ", "
344        }
345    }
346    
347    if (savedList != "") {
348        ToolTip("Saved Layout: " . RTrim(savedList, ", "))
349    } else {
350        ToolTip("No enabled apps detected to save.")
351    }
352    SetTimer () => ToolTip(), -3000
353}
354
355RestoreWorkspace(*) {
356    global INI_FILE, WORKSPACE_APPS
357    restoredList := ""
358    
359    for app in WORKSPACE_APPS {
360        if (app.enabled && WinExist(app.title)) {
361            try {
362                X := IniRead(INI_FILE, "Layout_" . app.name, "X", "")
363                if (X == "")
364                    continue
365                    
366                Y := IniRead(INI_FILE, "Layout_" . app.name, "Y")
367                W := IniRead(INI_FILE, "Layout_" . app.name, "W")
368                H := IniRead(INI_FILE, "Layout_" . app.name, "H")
369                isMax := IniRead(INI_FILE, "Layout_" . app.name, "Maximized")
370
371                WinRestore(app.title)
372                Sleep(50) 
373                WinMove(X, Y, W, H, app.title)
374                
375                if (app.name == "Epic") {
376                    Sleep(100)
377                }
378
379                if (isMax == 1) {
380                    WinMaximize(app.title)
381                }
382                restoredList .= app.disp . ", "
383            }
384        }
385    }
386    
387    if (restoredList != "") {
388        ToolTip("Restored Layout: " . RTrim(restoredList, ", "))
389    } else {
390        ToolTip("No layouts restored.")
391    }
392    SetTimer () => ToolTip(), -3000
393}
394
395; ==============================================================================
396; Core Logic
397; ==============================================================================
398SetTimer StopSleep, 100000
399SetTimer UpdateMarkerPos, 100 
400SetTimer UpdateLayoutDetection, 2000 
401
402LaunchVisage() {
403    if WinExist(VISAGE) {
404        WinActivate(VISAGE)
405        return
406    }
407    if WinExist(VISAGE_LOGIN) {
408        VisageLoginSequence()
409        return
410    }
411    targetLnk := ""
412    loop files A_Desktop "\*Visage*.lnk" {
413        targetLnk := A_LoopFileFullPath
414        break
415    }
416    if (targetLnk == "") {
417        loop files A_DesktopCommon "\*Visage*.lnk" {
418            targetLnk := A_LoopFileFullPath
419            break
420        }
421    }
422    if (targetLnk) {
423        Run(targetLnk)
424    } else {
425        fallbackPath := "C:\Program Files\Visage Imaging\Visage 7.1\bin\arch-Win\vsclient.exe"
426        if FileExist(fallbackPath) {
427            Run(fallbackPath)
428        } else {
429            MsgBox("Could not find Visage executable.", "Error", "Icon!")
430            return
431        }
432    }
433    if WinWait(VISAGE_LOGIN,, 20) {
434        VisageLoginSequence()
435    }
436}
437
438VisageLoginSequence() {
439    global VISAGE_LOGIN, LOGIN_STEP_DELAY
440    global Edit1, Edit2 
441    
442    if !WinExist(VISAGE_LOGIN)
443        return
444    WinActivate(VISAGE_LOGIN)
445    if !WinWaitActive(VISAGE_LOGIN,, 3)
446        return
447    
448    local safeUser := Edit1.Value
449    local safePass := Edit2.Value
450    
451    SetKeyDelay 10, 10
452    
453    WinGetPos(,, &winW, &winH, VISAGE_LOGIN)
454    oldMode := A_CoordModeMouse
455    CoordMode "Mouse", "Window"
456    
457    MouseMove(winW * 0.60, winH * 0.40) 
458    Sleep(LOGIN_STEP_DELAY)
459    Click()
460    Sleep(LOGIN_STEP_DELAY)
461
462    ClipSaved := ClipboardAll()
463
464    SendEvent("^a{Delete}")
465    Sleep(LOGIN_STEP_DELAY)
466    A_Clipboard := ""
467    A_Clipboard := "VISAGE.NYUMC.ORG"
468    ClipWait(1)
469    Send("^v")
470    Sleep(LOGIN_STEP_DELAY + 50)
471    SendEvent("{Tab}")
472    Sleep(LOGIN_STEP_DELAY)
473
474    SendEvent("^a{Delete}")
475    Sleep(LOGIN_STEP_DELAY)
476    A_Clipboard := ""
477    A_Clipboard := safeUser
478    ClipWait(1)
479    Send("^v")
480    Sleep(LOGIN_STEP_DELAY + 50)
481    SendEvent("{Tab}")
482    Sleep(LOGIN_STEP_DELAY)
483
484    A_Clipboard := ""
485    A_Clipboard := safePass
486    ClipWait(1)
487    Send("^v")
488    Sleep(LOGIN_STEP_DELAY + 200) 
489
490    SendEvent("{Enter}")
491    
492    Sleep(150)
493    A_Clipboard := ClipSaved
494    
495    CoordMode "Mouse", oldMode
496}
497
498; --- Fast Break Glass (Clipboard Injection) ---
499fastBreakGlass(*) {
500    global BTG_TAB_DELAY, Edit2
501
502    ClipSaved := ClipboardAll()
503
504    A_Clipboard := "" 
505    A_Clipboard := "Provision"
506    ClipWait(1)
507    Send("^v")
508    Sleep(BTG_TAB_DELAY + 50)
509    
510    Send("{Tab}")
511    Sleep(BTG_TAB_DELAY)
512    Send("{Tab}")
513    Sleep(BTG_TAB_DELAY)
514    
515    A_Clipboard := ""
516    A_Clipboard := Edit2.Value
517    ClipWait(1)
518    Send("^v")
519    Sleep(BTG_TAB_DELAY + 50)
520    
521    Send("!a")
522    
523    Sleep(150)
524    A_Clipboard := ClipSaved
525}
526
527loginSite() {
528    global Edit1, Edit2
529    
530    ClipSaved := ClipboardAll()
531
532    A_Clipboard := ""
533    A_Clipboard := Edit1.Value
534    ClipWait(1)
535    Send("^v")
536    Sleep(200)
537    Send("{Tab}")
538    Sleep(200)
539
540    A_Clipboard := ""
541    A_Clipboard := Edit2.Value
542    ClipWait(1)
543    Send("^v")
544    Sleep(200)
545    Send("{Enter}")
546
547    Sleep(150)
548    A_Clipboard := ClipSaved
549}
550
551; --- Bellevue Remote Desktop Login ---
552loginBellevue(*) {
553    global Edit3
554    KeyWait("Alt")
555    KeyWait("b")
556    Sleep(100)
557    SetKeyDelay 40, 40
558    SendEvent("{Raw}" Edit3.Value)
559    Sleep(200)
560    SendEvent("{Enter}")
561}
562
563; ==============================================================================
564; CAPSLOCK & MODIFIER HOTKEYS
565; ==============================================================================
566
567; --- Shift + CapsLock toggles the actual uppercase state ---
568+CapsLock::CapsLock
569
570; --- CapsLock intercepts ---
571#HotIf TRACKBALL_SCROLL
572    $CapsLock::TrackballScroll()
573#HotIf
574
575; --- Disable standard CapsLock press if Trackball scroll is off ---
576#HotIf !TRACKBALL_SCROLL
577    $CapsLock::return 
578#HotIf
579
580; --- Custom Rads Mode Modifiers ---
581#HotIf GetKeyState("CapsLock", "P")
582    f:: enableRadsMode()
583    d:: exitRadsMode()
584    w:: RestoreWorkspace()
585    c:: ForceRefreshControl()
586#HotIf
587
588; ==============================================================================
589; CAPSLOCK SCROLL
590; ==============================================================================
591TrackballScroll(*) {
592    global SCROLL_THRESHOLD, SCROLL_LOCK_RATIO
593    oldMode := A_CoordModeMouse
594    CoordMode "Mouse", "Screen"
595    MouseGetPos(&startX, &startY)
596    bankX := 0, bankY := 0
597    Loop {
598        if !GetKeyState("CapsLock", "P")
599            break
600        MouseGetPos(&currentX, &currentY)
601        moveX := currentX - startX, moveY := currentY - startY
602        if (moveX != 0 || moveY != 0) {
603            DllCall("SetCursorPos", "int", startX, "int", startY)
604        }
605        bankX += moveX, bankY += moveY
606        absX := Abs(bankX), absY := Abs(bankY)
607        if (absX > (absY * SCROLL_LOCK_RATIO)) {
608            if (absX >= SCROLL_THRESHOLD) {
609                ticks := Integer(absX / SCROLL_THRESHOLD)
610                direction := (bankX > 0) ? "{WheelRight}" : "{WheelLeft}"
611                Loop ticks
612                    Send(direction)
613                bankX := Mod(bankX, SCROLL_THRESHOLD), bankY := 0
614            }
615        } else if (absY > absX) {
616            if (absY >= SCROLL_THRESHOLD) {
617                ticks := Integer(absY / SCROLL_THRESHOLD)
618                direction := (bankY > 0) ? "{WheelDown}" : "{WheelUp}"
619                Loop ticks
620                    Send(direction)
621                bankY := Mod(bankY, SCROLL_THRESHOLD), bankX := 0
622            }
623        }
624        Sleep(5)
625    }
626    CoordMode "Mouse", oldMode
627}
628
629; ==============================================================================
630; UTILS & HOTKEYS
631; ==============================================================================
632GetTargetControl(forceRefresh := false) {
633    global PS
634    
635    largestArea := 0
636    bestControl := ""
637    
638    try {
639        ctrlList := WinGetControls(PS)
640        for ctrl in ctrlList {
641            if InStr(ctrl, "RICHEDIT") {
642                try {
643                    ; Ensure the control is visible
644                    if ControlGetVisible(ctrl, PS) {
645                        ControlGetPos(&x, &y, &w, &h, ctrl, PS)
646                        
647                        ; Filter out phantom formatting buffers
648                        if (w > 20 && h > 20) {
649                            area := w * h
650                            if (area > largestArea) {
651                                largestArea := area
652                                bestControl := ctrl
653                            }
654                        }
655                    }
656                } catch {
657                    continue 
658                }
659            }
660        }
661    }
662    
663    return bestControl
664}
665
666ActivateAndSend(key, targetSpecificControl := true) {
667    global PS
668    if !WinExist(PS)
669        return
670        
671    ; [ANTI-DEADLOCK FAST PATH]
672    ; Uses SendEvent for improved reliability with Nuance/Dragon hooks
673    if WinActive(PS) {
674        SendEvent(key)
675        return
676    }
677    
678    ; Slow path (if clicking back into PS from Epic/Visage)
679    WinActivate(PS)
680    if !WinWaitActive(PS,, 1)
681        return
682    Sleep(50)
683    
684    if targetSpecificControl {
685        target := GetTargetControl()
686        if (target) {
687            try {
688                if (ControlGetFocus(PS) != target) {
689                    ControlFocus(target, PS)
690                }
691            }
692        }
693    }
694    
695    SendEvent(key) 
696}
697
698StopSleep(*) {
699    if (KEEPAWAKE) {
700        SendEvent("{F15}")
701    }
702}
703
704pick(num) {
705    global PS
706    MouseGetPos &startX, &startY
707    CoordMode "Mouse", "Client" 
708    heightRow := 17
709    if WinExist(PS) {
710        try {
711            for ctrl in WinGetControls(PS) {
712                try {
713                    txt := ControlGetText(ctrl, PS)
714                } catch {
715                    continue
716                }
717                if (txt == "Pick List Choices") {
718                    ControlGetPos(&x, &y, &w, &h, ctrl, PS)
719                    targetY := y + Integer(heightRow/2) + (heightRow * num)
720                    targetX := x + 20
721                    if !WinActive(PS) {
722                        WinActivate(PS)
723                        WinWaitActive(PS,, 1)
724                    }
725                    Click(targetX, targetY)
726                    Sleep(50)
727                    Click(targetX, targetY)
728                    CoordMode "Mouse", "Screen"
729                    MouseMove(startX, startY)
730                    Sleep(50)
731                    ActivateAndSend("{Tab}", true)
732                    return
733                }
734            }
735        }
736    }
737    CoordMode "Mouse", "Screen"
738}
739
740; -- Common Rads Logic --
741toggleDictation(*) {
742    static lastToggle := 0
743    
744    ; Debounce to prevent double-triggers
745    if (A_TickCount - lastToggle < 500) {
746        return 
747    }
748    lastToggle := A_TickCount
749    
750    ; Routes through ActivateAndSend to ensure PowerScribe is targeted,
751    ; passing 'false' so it skips searching for a specific text control.
752    ActivateAndSend("{F4}", false)
753}
754
755saveDraft(*)       => ActivateAndSend("{F9}", false)
756nextField(*)       => ActivateAndSend("{Tab}", true)
757prevField(*)       => ActivateAndSend("+{Tab}", true)
758backspace(*)       => ActivateAndSend("{Backspace}", true)
759newLine(*)         => ActivateAndSend("{Enter}", true)
760
761enableRadsMode(*) {
762    global RADSMODE := true
763    GetTargetControl(true) ; Automatically flush and re-target when entering Rads Mode
764}
765exitRadsMode(*) {
766    global RADSMODE := false
767}
768
769ForceRefreshControl(*) {
770    GetTargetControl(true)
771    ToolTip("PowerScribe Target Refreshed")
772    SetTimer () => ToolTip(), -1500
773}
774
775; -- Global Hotkeys --
776!z:: fastBreakGlass()
777!p:: loginSite()
778
779!b:: loginBellevue()
780
781^!s:: SaveWorkspace()
782
783#HotIf RADSMODE
784    r::LButton
785    e::MButton
786    w::RButton
787    $d:: toggleDictation()
788    $h:: saveDraft()
789    $f:: nextField()
790    $g:: prevField()
791    $s:: backspace()
792    $a:: newLine()
793    $q:: Send("^w")
794    
795    ; -- Pick List Hotkeys --
796    $1:: (WinActive(PS) ? pick(1) : Send("1")) 
797    $2:: (WinActive(PS) ? pick(2) : Send("2")) 
798    $3:: (WinActive(PS) ? pick(3) : Send("3")) 
799    $4:: (WinActive(PS) ? pick(4) : Send("4")) 
800    $5:: (WinActive(PS) ? pick(5) : Send("5"))
801
802    $z:: (WinActive(PS) ? "" : Send("z"))
803    $x:: (WinActive(PS) ? "" : Send("x"))
804    $c:: (WinActive(PS) ? "" : Send("c"))
805    $v:: (WinActive(PS) ? "" : Send("v"))
806#HotIf
807

This is the full source code of the RadMode.ahk file. You can copy this into a new .ahk file or download the file directly using the button above.