Use hotkeys to activate buttons... (Windows)
Posted: Fri Mar 20, 2020 5:26 pm
I am using some nice programs (for example the cool PDFXChange Viewer or the Purebasic IDE) which don't support shortcuts for all dialogs. Therefore I've written the following tool which simplifies controlling these programs by using the keyboard.
As soon a Win+Alt+Character hotkey is pressed, the tool scans the active window if there's a matching name for any object and tries to activate it.
Don't forget to add some keywords in the data section as you like.
Have fun!
As soon a Win+Alt+Character hotkey is pressed, the tool scans the active window if there's a matching name for any object and tries to activate it.
Don't forget to add some keywords in the data section as you like.
Have fun!
Code: Select all
; Define
EnableExplicit
#SysTray=1
#ApplicationTitle="·:H:·"
Global WinID
Global HotKey
Global Scan
Global Quit
Global Active=#True
Structure ObjectType
Handle.i
Title.s
Class.s
EndStructure
#CharByte=SizeOf(Character)
#CharShift=#CharByte>>1
#ObjectTextLength=256
#Hotkeys=26
#Window=0
Enumeration
#PopupMenu
#PopupState
#PopupQuit
EndEnumeration
DataSection
Keywords:
Data.s "|abort|apply|abbrechen|enable inline asm syntax coloring"; a
Data.s ""; b
Data.s "|cancel|close"; c
Data.s ""; d
Data.s ""; e
Data.s "|find next"; f
Data.s ""; g
Data.s ""; h
Data.s "|search inside selection only"; i
Data.s ""; j
Data.s ""; k
Data.s "|replace all"; l
Data.s "|don't search in comments|enable modern theme support (for windows xp and above)"; m
Data.s ""; n
Data.s "|ok|okay"; o
Data.s ""; p
Data.s ""; q
Data.s "|replace"; r
Data.s "|case sensitive"; s
Data.s "|create threadsafe executable"; t
Data.s "|create unicode executable"; u
Data.s ""; v
Data.s "|whole words only"; w
Data.s ""; x
Data.s ""; y
Data.s ""; z
EndDataSection
Global Dim mem.i(#Hotkeys)
CompilerIf #SysTray
#IconSize=1150; RGB/A 16x16
DataSection
Icon:
Data.q $1010000100010000,$468002000010000,$28000000160000,$20000000100000,$2000010000,$4400000,0,$19B2000000000000,$4CFF15004CFF00,$4CFF15004CFF15,$4CFF15004CFF15,$4CFF15004CFF15,$4CFF15004CFF15,$4CFF15004CFF15,$4CFF15004CFF15,$66B2FF15004CFF15,$127FFF00127FFF00,$127FFF00127FFF00
Data.q $127FFF00127FFF00,$127FFF00127FFF00,$127FFF00127FFF00,$127FFF00127FFF00,$127FFF00127FFF00,$66B2FF15004CFF00,$127FFF00127FFF00,$127FFF00127FFF00,$127FFF00127FFF00,$127FFF00127FFF00,$127FFF00127FFF00,$127FFF00127FFF00,$127FFF00127FFF00,$66B2FF15004CFF00,$127FFF00127FFF00
Data.q $83E5FF00127FFF00,$19B2FF0083E5FF00,$127FFF00127FFF00,$83E5FF00127FFF00,$19B2FF0083E5FF00,$127FFF00127FFF00,$66B2FF15004CFF00,$127FFF00127FFF00,$83E5FF00127FFF00,$19B2FF0083E5FF00,$127FFF00127FFF00,$83E5FF00127FFF00,$19B2FF0083E5FF00,$127FFF00127FFF00,$66B2FF15004CFF00
Data.q $127FFF00127FFF00,$83E5FF00127FFF00,$19B2FF0083E5FF00,$127FFF00127FFF00,$83E5FF00127FFF00,$19B2FF0083E5FF00,$127FFF00127FFF00,$66B2FF15004CFF00,$127FFF00127FFF00,$83E5FF00127FFF00,$19B2FF0083E5FF00,$127FFF00127FFF00,$83E5FF00127FFF00,$19B2FF0083E5FF00,$127FFF00127FFF00
Data.q $66B2FF15004CFF00,$127FFF00127FFF00,$83E5FF00127FFF00,$83E5FF0083E5FF00,$83E5FF0083E5FF00,$83E5FF0083E5FF00,$19B2FF0083E5FF00,$127FFF00127FFF00,$66B2FF15004CFF00,$127FFF00127FFF00,$83E5FF00127FFF00,$83E5FF0083E5FF00,$83E5FF0083E5FF00,$83E5FF0083E5FF00,$19B2FF0083E5FF00
Data.q $127FFF00127FFF00,$66B2FF15004CFF00,$127FFF00127FFF00,$83E5FF00127FFF00,$19B2FF0083E5FF00,$127FFF00127FFF00,$83E5FF00127FFF00,$19B2FF0083E5FF00,$127FFF00127FFF00,$66B2FF15004CFF00,$127FFF00127FFF00,$83E5FF00127FFF00,$19B2FF0083E5FF00,$127FFF00127FFF00,$83E5FF00127FFF00
Data.q $19B2FF0083E5FF00,$127FFF00127FFF00,$66B2FF15004CFF00,$127FFF00127FFF00,$83E5FF00127FFF00,$19B2FF0083E5FF00,$127FFF00127FFF00,$83E5FF00127FFF00,$19B2FF0083E5FF00,$127FFF00127FFF00,$66B2FF15004CFF00,$127FFF00127FFF00,$83E5FF00127FFF00,$19B2FF0083E5FF00,$127FFF00127FFF00
Data.q $83E5FF00127FFF00,$19B2FF0083E5FF00,$127FFF00127FFF00,$66B2FF15004CFF00,$127FFF00127FFF00,$127FFF00127FFF00,$127FFF00127FFF00,$127FFF00127FFF00,$127FFF00127FFF00,$127FFF00127FFF00,$127FFF00127FFF00,$66B2FF15004CFF00,$127FFF00127FFF00,$127FFF00127FFF00,$127FFF00127FFF00
Data.q $127FFF00127FFF00,$127FFF00127FFF00,$127FFF00127FFF00,$127FFF00127FFF00,$66B2FF15004CFF00,$66B2FF0066B2FF00,$66B2FF0066B2FF00,$66B2FF0066B2FF00,$66B2FF0066B2FF00,$66B2FF0066B2FF00,$66B2FF0066B2FF00,$66B2FF0066B2FF00,$FF0019B2FF00,0,0,0,0,0,0,0,0
EndDataSection
CompilerEndIf
; EndDefine
Procedure GetObjectInfo_(*Object.ObjectType,Set=#False)
#MaxTextLength=256
With *Object
If Set
\Handle=Set
EndIf
If \Handle
\Title=Space(#MaxTextLength)
\Class=Space(#MaxTextLength)
GetWindowText_(\Handle,\Title,#MaxTextLength)
GetClassName_(\Handle,\Class,#MaxTextLength)
ProcedureReturn #True
Else
ProcedureReturn #False
EndIf
EndWith
EndProcedure
Procedure.s ActivateObject(handle)
Protected Class.s
Class=Space(#ObjectTextLength)
GetClassName_(Handle,@Class,#ObjectTextLength)
class=LCase(class)
Select class
Case "static"
PostMessage_(GetWindow_(Handle,#GW_HWNDNEXT),#WM_ACTIVATE,#WA_ACTIVE,0)
Case "button"
;PostMessage_(handle,#WM_LBUTTONDOWN,#MK_LBUTTON,0)
;Delay(100)
;PostMessage_(handle,#WM_LBUTTONUP,#MK_LBUTTON,0)
PostMessage_(handle,#BM_CLICK,#MK_LBUTTON,0)
Default
PostMessage_(handle,#WM_ACTIVATE,#WA_ACTIVE,0)
EndSelect
Scan=#False
EndProcedure
Procedure.s GetObjectInfo(handle)
Protected n,c,*mem
Protected Title.s
Protected s.s
Title=Space(#ObjectTextLength)
GetWindowText_(Handle,@Title,#MaxTextLength)
If Title
n=FindString(title,"&")
If n
n=PeekA(@Title+n<<#CharShift)&$DF-'@'
If n=hotkey
ActivateObject(handle)
;PostMessage_(handle,#BM_CLICK,#MK_LBUTTON,0)
EndIf
Else
title=Trim(LCase(Title))
*mem=mem(HotKey)
If *mem
Repeat
c=PeekA(*mem)
If c
If title=PeekS(*mem+1,c)
ActivateObject(handle)
EndIf
*mem+c+1
EndIf
Until c=0
EndIf
EndIf
EndIf
EndProcedure
Procedure GetObjectTree(handle)
Protected child
Repeat
GetObjectInfo(handle)
child=GetWindow_(Handle,#GW_CHILD)
If child
GetObjectTree(child)
EndIf
handle=GetWindow_(Handle,#GW_HWNDNEXT)
Until handle=0 Or Scan=0
EndProcedure
Procedure ScanNow()
Protected handle
Protected s.s
handle=GetForegroundWindow_()
If handle
handle=GetWindow_(Handle,#GW_CHILD)
If handle
Scan=#True
GetObjectTree(handle)
EndIf
EndIf
EndProcedure
Procedure ActivateHotkeys(mode)
Protected n
If mode
RegisterHotKey_(WinID,600,#MOD_ALT|#MOD_SHIFT|#MOD_WIN,#VK_Q)
For n=0 To #Hotkeys-1
RegisterHotKey_(WinID,601+n,#MOD_ALT|#MOD_WIN,#VK_A+n)
Next n
Else
For n=0 To #Hotkeys
UnregisterHotKey_(WinID,600+n)
Next n
EndIf
EndProcedure
Procedure Main()
Protected c,i,n
Protected *mem
Protected *pipe
WinID=OpenWindow(#Window,8,8,8,8,#ApplicationTitle,#PB_Window_Invisible|#PB_Window_BorderLess)
CompilerIf #SysTray
AddSysTrayIcon(#SysTray,WinID,CatchImage(#SysTray,?Icon))
SysTrayIconToolTip(#SysTray,"Hotkey by Michael Vogel")
CreatePopupMenu(#PopupMenu)
MenuItem(#PopupState,"Toggle Hotkey State")
MenuItem(#PopupQuit,"Quit Hotkeys…")
CompilerElse
AddKeyboardShortcut(0,#PB_Shortcut_Escape,#PopupQuit)
SetWindowColor(0,#Yellow)
HideWindow(0,0)
CompilerEndIf
; Initialize Keywords...
*mem=?Keywords
For i=1 To #Hotkeys
n=0
*pipe=0
mem(i)=*mem
Repeat
c=PeekA(*mem)
Select c
Case #Null
If *pipe
PokeA(*pipe,n)
EndIf
Case '|'
If *pipe
PokeA(*pipe,n)
EndIf
*pipe=*mem
Default
CompilerIf #PB_Compiler_Debugger
If *pipe=0
Debug "Illegal Data - "+PeekS(*mem)+" pipe symbol missing."
End
EndIf
CompilerEndIf
n+1
EndSelect
*mem+#CharByte
Until c=#Null
Next i
ActivateHotkeys(#True)
Repeat
Select WaitWindowEvent()
Case #WM_HOTKEY
n=EventwParam()
Select n
Case 600
PostEvent(#PB_Event_CloseWindow)
Case 601 To 626
If Active
HotKey=n-600
ScanNow()
EndIf
EndSelect
Case #PB_Event_CloseWindow
quit=#True
CompilerIf #SysTray
Case #PB_Event_SysTray
Select EventType()
Case #PB_EventType_LeftClick
DisplayPopupMenu(#PopupMenu,WinID)
Case #PB_EventType_RightClick
quit=#True
Case #PB_EventType_LeftDoubleClick
PostEvent(#PB_Event_Menu,#Window,#PopupState)
EndSelect
CompilerEndIf
Case #PB_Event_Menu;#PB_Event_Gadget
Select EventGadget()
Case #PopupQuit
quit=#True
CompilerIf #SysTray
Case #PopupState
For n=0 To 15
For i=0 To 15
*mem=?Icon+62+(n+i<<4)<<2
PokeL(*mem,PeekL(*mem)!$00FF00FF)
Next i
Next n
ChangeSysTrayIcon(#SysTray,CatchImage(#SysTray,?Icon))
Active!1
CompilerEndIf
EndSelect
EndSelect
Until quit
ActivateHotkeys(#False)
End
EndProcedure
If FindWindow_(0,#ApplicationTitle)=0
Main()
EndIf