Multiple Dynamic HotKeys in a single ahk file

Get help with using AutoHotkey and its commands and hotkeys
sqlcode
Posts: 27
Joined: 02 Nov 2017, 08:55

Multiple Dynamic HotKeys in a single ahk file

12 Dec 2017, 00:32

First of all, I have looked a lot of post that talks about putting multiple hotkeys in a single ahk file but i didn't find concrete answer to my questions.

I am trying to automate series of tasks in/on a single instance of IE for intranet application. Flow looks something like below :-

1) Login to Twitter. Lets call this individual script as 1_login.ahk.
2) Compose a tweet. 2_compose.ahk
3) Search for keyword. 3_search_keyword_tweet.ahk
4) Retweet and like. 4_rt_like.ahk

In this example, I would like to have a functionality where each user can assign their own hotkeys. For Example, I may use Control + A to execute step#1(1_login.ahk) to login but other person might prefer Control + B to execute same script (i.e. 1_login.ahk). My intention is to build a small gui that lets them pick hotkey and select a file from their drive that they want autohotkeys assigned to. I have a master list of ahk files so in my example above, i can only assign 4 unique hotkey but key combination is a personal choice of each user.

I have about 400-500 of such small scripts that needs to be implemented and given to users so you can imagine maint. nightmare this could create if i don't handle this well.

My questions are :
1) With this in mind, what's the best way to implement? Should I use, functions, includes or something else?
2) When user selects a hot key, I plan to capture their hotkey and script path and write them to master file which will be placed in startup folder. This way, I will have only one AHK file running (master.ahk) which will control execution of all the scripts. Is this a good approach? PROS and CONS if you have implemented something similar? I am trying to manage a central repository of all the AHK scripts and users will only have master script on their local drive.

I would appreciate if someone can lead me to similar implementation or blog post or any other references.

Thanks,
User avatar
Exaskryz
Posts: 2876
Joined: 17 Oct 2015, 20:28

Re: Multiple Dynamic HotKeys in a single ahk file

12 Dec 2017, 00:35

If the scripts are a one-and-done kind of thing (they are not #Persistent) then I think just doing Run for each AHK script is fine.

I recommend using IniWrite/IniRead with your GUI and using the Hotkey command to control the Hotkeys assigned by users.
sqlcode
Posts: 27
Joined: 02 Nov 2017, 08:55

Re: Multiple Dynamic HotKeys in a single ahk file

12 Dec 2017, 09:42

Thank you. Would you have an example of similar script for reference?
User avatar
Exaskryz
Posts: 2876
Joined: 17 Oct 2015, 20:28

Re: Multiple Dynamic HotKeys in a single ahk file

12 Dec 2017, 12:49

I wouldn't, but here's a script I just made up to demonstrate:

Code: Select all

IniRead, ini1, hotkeys.ini, hotkeys, Hotkey1, Error
IniRead, ini2, hotkeys.ini, hotkeys, Hotkey2, Error

If (ini1!="Error")
Hotkey, %ini1%, label1
If (ini2!="Error")
Hotkey, %ini2%, label2

Gui, Add, Text,,Hotkey #1:
Gui, Add, Hotkey, vHK1, %ini1% ; If it's "Error", the Hotkey control will compensate and say there is no hotkey value ("None")
Gui, Add, Text,,Hotkey #2:
Gui, Add, Hotkey, vHK2, %ini2%
Gui, Add, Button, gSubmit, Submit
Gui, Add, Edit, , Click Here To Test Hotkeys ; (remove focus from Hotkey control)
Gui, Show
return

Submit:
Gui, Submit, NoHide
If HK1 ; if it has a value
{
If (ini1!="Error")
    Hotkey, %ini1%, Off ; turn off what was set before, if one was set
IniWrite, %HK1%, hotkeys.ini, hotkeys, Hotkey1
Hotkey, %HK1%, label1
ini1:=HK1 ; now we overwrite the initial value of ini1 with our new value, which was written to the Ini file anyhow. This just skips doing a read step. We want this so that if the user changes the Hotkey another time, we'll turn off the previous hotkey
}
If HK2
{
If (ini2!="Error")
    Hotkey, %ini2%, Off  ; turn off what was set before, if one was set
IniWrite, %HK2%, hotkeys.ini, hotkeys, Hotkey2
Hotkey, %HK2%, label2
ini2:=HK2 ; now we overwrite the initial value of ini1 with our new value, which was written to the Ini file anyhow. This just skips doing a read step. We want this so that if the user changes the Hotkey another time, we'll turn off the previous hotkey
}
return

label1:
MsgBox Hello
return

label2:
MsgBox World
return

This isn't perfect code. In quick testing, I've realized that if you try to disable a hotkey by making the Hotkey control in the GUI get a "None" value (press and release the Ctrl key is how I did it), and you submit that, HK1 and HK2 have no value. Thus, the If statements in the Submit: routine are false and we never turn off the previous hotkeys. So I think that the

Code: Select all

If (ini1!="Error")
    Hotkey, %ini1%, Off ; turn off what was set before, if one was set
Just needs to be moved outside of the If HK1 block (and same for ini2/HK2). But I don't know if that will have other consequences to how the code behaves. I think it would be fine though.
sqlcode
Posts: 27
Joined: 02 Nov 2017, 08:55

Re: Multiple Dynamic HotKeys in a single ahk file

12 Dec 2017, 17:09

Thanks a lot for code snippet. It helps a lot. I should have clarified earlier that by example, if you are aware of any github repo that has implemented something similar. But your example is also good enough to get me started.

From your example, it seems each one of those HK* (HK1,HK2) has to be predefined? Is there anyway we can make it variable (HK_some number?
User avatar
Exaskryz
Posts: 2876
Joined: 17 Oct 2015, 20:28

Re: Multiple Dynamic HotKeys in a single ahk file

12 Dec 2017, 17:23

I would do a Loop and use the variable A_Index. See expressions for doing the double deref. (My example below doesn't put the _ after the K, but feel free to add it where you prefer on variables. HK_%A_Index% is perfectly legit.

Code: Select all

Loop, 2
    IniRead, ini%A_Index%, hotkeys.ini, hotkeys, Hotkey%A_Index%, Error

Loop, 2
   If (ini%A_Index%!="Error")
       Hotkey, % ini%A_Index%, label%A_Index%


Loop, 2
    {
    Gui, Add, Text,,Hotkey #%A_Index%:
    Gui, Add, Hotkey, vHK%A_Index%, % ini%A_Index% ; If it's "Error", the Hotkey control will compensate and say there is no hotkey value ("None")
    }

; other GUI code

Submit:
Gui, Submit, NoHide
Loop, 2
    If HK1 ; if it has a value
    {
    If (ini%A_Index%!="Error")
        Hotkey, % ini%A_Index%, Off ; turn off what was set before, if one was set
    IniWrite, % HK%A_Index%, hotkeys.ini, hotkeys, Hotkey%A_Index%
    Hotkey, % HK%A_Index%, label%A_Index%
    ini%A_Index%:=HK%A_Index% ; now we overwrite the initial value of ini1 with our new value, which was written to the Ini file anyhow. This just skips doing a read step. We want this so that if the user changes the Hotkey another time, we'll turn off the previous hotkey
    }

label1: ; and label 2 still hardcoded
MsgBox Hello
return
A_AhkUser
Posts: 1076
Joined: 06 Mar 2017, 16:18
GitHub: AAhkUser
Location: France

Re: Multiple Dynamic HotKeys in a single ahk file

12 Dec 2017, 22:35

With dynamic hotkeys I'd specify the word ON since a volatile user can set anew the same key to the same label, actually:
If the label or function is specified but the hotkey is disabled from a previous use of this command, the hotkey will remain disabled. To prevent this, include the word ON in Options.
source: https://www.autohotkey.com/docs/command ... Parameters

Code: Select all

Loop, 2
    IniRead, ini%A_Index%, %A_ScriptDir%\hotkeys.ini, hotkeys, Hotkey%A_Index%, Error

GUI, +hwndID
Gui, Add, Edit, w300 ; to test in it: actally this prevent 'u' hotkey from being catch by any of both hotkey controls
Loop, 2
   If (ini%A_Index%!="Error")
       Hotkey, % ini%A_Index%, label%A_Index%


Loop, 2
    {
    Gui, Add, Text,,Hotkey #%A_Index%:
    Gui, Add, Hotkey, vHK%A_Index%, % ini%A_Index% ; If it's "Error", the Hotkey control will compensate and say there is no hotkey value ("None")
    }

Gui, Show
return
u::
Submit:
Gui, Submit, NoHide
Loop, 2
    If HK1 ; if it has a value
    {
    If (ini%A_Index%!="Error")
        Hotkey, % ini%A_Index%, Off ; turn off what was set before, if one was set
    IniWrite, % HK%A_Index%, hotkeys.ini, hotkeys, Hotkey%A_Index%
    Hotkey, % HK%A_Index%, label%A_Index%, On ; added On
    ini%A_Index%:=HK%A_Index% ; now we overwrite the initial value of ini1 with our new value, which was written to the Ini file anyhow. This just skips doing a read step. We want this so that if the user changes the Hotkey another time, we'll turn off the previous hotkey
    }
return
label1: ; and label 2 still hardcoded
label2:
ToolTip Hello
return
Btw the problem become more complex if it is question of context-sensitive hotkeys (using (Not)?(Active|Exist)) since Hotkey (Not)?(Active|Exist) puts context sensitivity into effect for all subsequently created or modified hotkeys.
sqlcode
Posts: 27
Joined: 02 Nov 2017, 08:55

Re: Multiple Dynamic HotKeys in a single ahk file

14 Dec 2017, 11:35

I was searching in the forum and came across this old post from jaco0646. I am trying to implement Example#4 from his post with some additions. What i am trying to add is a browse button (GUI, Add, Button, ym gBtnBrowse, &Browse ) that lets user select the path of ahk exe file. I am new to AHK and GUI in general from his script, i understand that i need to add, browse button to the gui and to the file but i am getting stuck in error. Later in his post, jaco0646 did mentioned and explained how to call exe on button controls but i am stuck on browse part where user would have the ability to select files from different location using browse button.

Could anyone please help?

https://autohotkey.com/board/topic/4743 ... c-hotkeys/
sqlcode
Posts: 27
Joined: 02 Nov 2017, 08:55

Re: Multiple Dynamic HotKeys in a single ahk file

14 Dec 2017, 16:57

Btw the problem become more complex if it is question of context-sensitive hotkeys (using (Not)?(Active|Exist)) since Hotkey (Not)?(Active|Exist) puts context sensitivity into effect for all subsequently created or modified hotkeys.
Hello,
I don't need context-sensitive hotkeys. For most part, i am trying to use Alt, Ctrl + Key combination. I gave a reference to the old post in my above post. That gives me most everything i want, except, i am trying to add an option to select and show the path of ahk (.exe) file. I tried to add file path, but it is not getting written to the file.



Thanks,
A_AhkUser
Posts: 1076
Joined: 06 Mar 2017, 16:18
GitHub: AAhkUser
Location: France

Re: Multiple Dynamic HotKeys in a single ahk file

14 Dec 2017, 21:33

Hi sqlcode,
I am trying to add an option to select and show the path of ahk (.exe) file. I tried to add file path, but it is not getting written to the file.
Here's some references:
FileSelectFile (to display a dialog that allows the user to select a file)
GuiControl (amongs others, to set the text of a control in a GUI window)
GuiCOntrolGet (among others, to retireve user's input in a GUI window)

Here's a commented example from the codes above implementing this functionality, hoping it could help you:

Code: Select all

Hotkey, IfWinNotActive, test
if not (FileExist(myIniFile:=A_ScriptDir . "\hotkeys_settings.ini")) { ; if the ini file doesn't exist yet

	FileAppend,
	(LTrim
	[hotkeys]
	function1=!a
	function2=!z
	function3=!e
	function4=!r
	function5=!t
	function6=!y
	[executable]
	path=
	), % myIniFile, utf-16 ; creates it

}
GUI, HK:New, +LastFound
GUI, HK:Margin, 10, 10

IniRead, outputVarSection, % myIniFile, hotkeys ; reads the hotkeys section of the ini file
keysAndValues := StrSplit(outputVarSection, ["=", "`n"]) ; split the sction using '=' and the linefeed character as delimiters
hotkeysList := hotkeyControlList := [] ; two arrays to keeps track of hotkeys and hotkeys controls
i := 1 ; initializes an index; used in the loop above
Loop % keysAndValues.length()//2 { ; this creates hotkeys controls depending on how many hotkeys are defined in the ini file
	
	GUI, HK:Add, Text, xm Section, % "myHotkey" . a_index
	GUI, HK:Add, Hotkey, limit1 ys hwndID%a_index%, % (var := var%a_index% := keysAndValues[++i])
	hotkeysList.push(var), hotkeyControlList[a_index] := ID%a_index%
	if (var <> "ERROR" and IsLabel("label" . a_index)) { ; if the key and the label fit to the hotkey command requisits...
	   Hotkey, % var, label%a_index%
	}
	i++ ; so that is will become anew an odd number befor being incremented
    
}
IniRead, exePath, % myIniFile, executable, path
GUI, HK:Add, Edit, xm Section w300 r1 +ReadOnly vEditControl, % (exePath = "ERROR") ? "" : exePath
GUI, HK:Add, Button, ys gget, Get executable ; each time the button 'Get executable' is pressed 'get' subroutine will be run
GUI, HK:Add, Button, w80 gsaveSettings, &OK ; each time the button 'OK' is pressed 'saveSettings' subroutine will be run
GUI, HK:Show, AutoSize Center, test
return


get: ;  'get' subroutine
selectedFile := ""
FileSelectFile, selectedFile, 1, %A_MyDocuments%, Select executable, (*.exe)
SplitPath, % selectedFile,,, outExtension
if (!ErrorLevel and outExtension = "exe") { ; if the user did not dismiss the dialog and choose an executable...
	GuiControl, HK:, EditControl, % selectedFile ; set the value of the edit control to be the full path of the selected file
}
return

saveSettings:
inputList := Chr(44) ; chr 44 is the comma character
for index, ID in hotkeyControlList { ; repeats a series of commands once for each key-value pair in hotkeyControlList
	GuiControlGet, outputVar,, % ID ; retrieves the user's input for the control
	if outputVar not in %inputList%
	{
	inputList .= outputVar . "," ; appends the input to the list
	if (outputVar <> "") { ; if user's input is not empty...
	var := var%index%
		if (var <> "ERROR")
			Hotkey, % var, Off
		IniWrite % outputVar, % myIniFile, hotkeys, function%index% ; writes this value @ hotkeys-functionX in ini file
		Hotkey, % outputVar, label%A_Index%, On
		var%index% := outputVar
	}
	} else {
		MsgBox, 64, test, duplicate hotkey, specifically: %index% 
	return
	}
}
GuiControlGet, selectedFile, HK:, EditControl, ; retrieves the value of the edit control, if any
IniWrite % selectedFile, % myIniFile, executable, path ; writes this value @ executable-path in ini file
return ; end of the subroutine

label1:
label2:
label3:
label4:
label5:
label6:
MsgBox % A_ThisLabel
return


[EDIT]
I modified it so that it also takes into account the clumsy user that input a duplicate hotkey...
Btw, you should at least add the following on the top of the script (at least before any use of the hotkey command):

Code: Select all

Hotkey, IfWinNotActive, titleOfTheGUI
in order to exempt this GUI from running any subroutine associated with a hotkey while the user are still specifying them.
Last edited by A_AhkUser on 14 Dec 2017, 21:57, edited 1 time in total.
sqlcode
Posts: 27
Joined: 02 Nov 2017, 08:55

Re: Multiple Dynamic HotKeys in a single ahk file

14 Dec 2017, 21:50

May be i didn't quite understood your script but i am only "getting(edited later)" single path option. I need one for each hotkey. Also when i try to select a path and run the script next time, it doesn't really pull up my saved path/file name.

More like below

Hotkey1 (Hot Key Text box without any label) - TextBox for File Path1
Hotkey2 (Hot Key Text box without any label) - TextBox for File Path2
Hotkey3 (Hot Key Text box without any label) - TextBox for File Path3
Hotkey4 (Hot Key Text box without any label) - TextBox for File Path4
sqlcode
Posts: 27
Joined: 02 Nov 2017, 08:55

Re: Multiple Dynamic HotKeys in a single ahk file

14 Dec 2017, 22:09

I tried your updated code but i am still getting option to select one path only. I need to add/save paths for all the different ahk/exe files. they could be stored in a different place.
sqlcode
Posts: 27
Joined: 02 Nov 2017, 08:55

Re: Multiple Dynamic HotKeys in a single ahk file

14 Dec 2017, 22:38

Since I am unable to post screenshot, here is the code. It is almost same as in jaco0646 post which i have mentioned above. I am struggling with how to add respective file path and read them back on.

Code: Select all

#SingleInstance force
#NoEnv
SetBatchLines, -1

#ctrls = 5 ;How many Hotkey controls to add?1
Loop,% #ctrls {
 Gui, Add, Text, xm, Enter Hotkey #%A_Index%:
 IniRead, savedHK%A_Index%, Hotkeys.ini, Hotkeys, %A_Index%, %A_Space%
 IniRead, savedFL%A_Index%, Hotkeys.ini, Hotkeys, %A_Index%, %A_Space%
 If savedHK%A_Index%                                       ;Check for saved hotkeys in INI file.
  Hotkey,% savedHK%A_Index%, Label%A_Index%                 ;Activate saved hotkeys if found.
  Edit,% savedFL%A_Index%, Label%A_Index%
 StringReplace, noMods, savedHK%A_Index%, ~                  ;Remove tilde (~) and Win (#) modifiers...
 StringReplace, noMods, noMods, #,,UseErrorLevel              ;They are incompatible with hotkey controls (cannot be shown).
 Gui, Add, Hotkey, x+5 vHK%A_Index% gGuiLabel, %noMods%        ;Add hotkey controls and show saved hotkeys.
 Gui, Add, Edit, x+5 vMyFile%A_Index%,
 GUI, Add, Button, x+5 vFL%A_Index% gFlLabel, Browse 
}
Gui, Show,,Dynamic Hotkeys
return
GuiClose:
 ExitApp

GuiLabel:

If InStr(%A_GuiControl%,"vk07")            ;vk07 = MenuMaskKey (see below)
  GuiControl,,%A_GuiControl%, % lastHK      ;Reshow the hotkey, because MenuMaskKey clears it.
return

FlLabel:
FileSelectFile,SelectedFile


If SelectedFile
  ;GuiControl,,%A_GuiControl%, % lastHK
  GuiControl,, MyFile%A_Index%, %SelectedFile%
; validateFL(A_GuiControl)
return


validateHK(GuiControl) {
 global lastHK
 Gui, Submit, NoHide
 lastHK := %GuiControl%                     ;Backup the hotkey, in case it needs to be reshown.
 num := SubStr(GuiControl,3)                ;Get the index number of the hotkey control.
 If (HK%num% != "") {                       ;If the hotkey is not blank...
  StringReplace, HK%num%, HK%num%, SC15D, AppsKey      ;Use friendlier names,
  StringReplace, HK%num%, HK%num%, SC154, PrintScreen  ;  instead of these scan codes.
  If CB%num%                                ;  If the 'Win' box is checked, then add its modifier (#).
   HK%num% := "#" HK%num%
  If !RegExMatch(HK%num%,"[#!\^\+]")        ;  If the new hotkey has no modifiers, add the (~) modifier.
   HK%num% := "~" HK%num%                   ;    This prevents any key from being blocked.
  checkDuplicateHK(num)
 }
 If (savedHK%num% || HK%num%)               ;Unless both are empty,
  setHK(num, savedHK%num%, HK%num%)         ;  update INI/GUI
  setFL(num, savedFL%num%, FL%num%)
}
/*
validateFL(GuiControl) {
 global lastFL
 Gui, Submit, NoHide
 lastFL := %GuiControl%                     ;Backup the hotkey, in case it needs to be reshown.
 num := SubStr(GuiControl,3)                ;Get the index number of the hotkey control.
 If (savedFL%num% || FL%num%)               ;Unless both are empty,
  setFL(num, savedFL%num%, FL%num%)         ;  update INI/GUI
}
*/

checkDuplicateHK(num) {
 global #ctrls
 Loop,% #ctrls
  If (HK%num% = savedHK%A_Index%) {
   dup := A_Index
   Loop,6 {
    GuiControl,% "Disable" b:=!b, HK%dup%   ;Flash the original hotkey to alert the user.
    Sleep,200
   }
   GuiControl,,HK%num%,% HK%num% :=""       ;Delete the hotkey and clear the control.
   break
  }
}

setHK(num,INI,GUI) {
 If INI                           ;If previous hotkey exists,
  Hotkey, %INI%, Label%num%, Off  ;  disable it.
 If GUI                           ;If new hotkey exists,
  Hotkey, %GUI%, Label%num%, On   ;  enable it.
 IniWrite,% GUI ? GUI:null, Hotkeys.ini, Hotkeys, %num%
 savedHK%num%  := HK%num%
 TrayTip, Label%num%,% !INI ? GUI " ON":!GUI ? INI " OFF":GUI " ON`n" INI " OFF"
}

setFL(num,INI,GUI) {
 If INI                           ;If previous hotkey exists,
  Hotkey, %INI%, Label%num%, Off  ;  disable it.
 If GUI                           ;If new hotkey exists,
  Hotkey, %GUI%, Label%num%, On   ;  enable it.
 IniWrite,% GUI ? GUI:null, Hotkeys.ini, Hotkeys, %num%
 savedFL%num%  := FL%num%
 TrayTip, Label%num%,% !INI ? GUI " ON":!GUI ? INI " OFF":GUI " ON`n" INI " OFF"
}


#MenuMaskKey vk07                 ;Requires AHK_L 38+
#If ctrl := HotkeyCtrlHasFocus()
 *AppsKey::                       ;Add support for these special keys,
 *BackSpace::                     ;  which the hotkey control does not normally allow.
 *Delete::
 *Enter::
 *Escape::
 *Pause::
 *PrintScreen::
 *Space::
 *Tab::
  modifier := ""
  If GetKeyState("Shift","P")
   modifier .= "+"
  If GetKeyState("Ctrl","P")
   modifier .= "^"
  If GetKeyState("Alt","P")
   modifier .= "!"
  Gui, Submit, NoHide             ;If BackSpace is the first key press, Gui has never been submitted.
  If (A_ThisHotkey == "*BackSpace" && %ctrl% && !modifier)   ;If the control has text but no modifiers held,
   GuiControl,,%ctrl%                                       ;  allow BackSpace to clear that text.
  Else                                                     ;Otherwise,
   GuiControl,,%ctrl%, % modifier SubStr(A_ThisHotkey,2)  ;  show the hotkey.
  validateHK(ctrl)
 return
#If

HotkeyCtrlHasFocus() {
 GuiControlGet, ctrl, Focus       ;ClassNN
 If InStr(ctrl,"hotkey") {
  GuiControlGet, ctrl, FocusV     ;Associated variable
  Return, ctrl
 }
}

;These labels may contain any commands for their respective hotkeys to perform.
Label1:
 MsgBox,% A_ThisLabel "`n" A_ThisHotkey
return
Label2:
 MsgBox,% A_ThisLabel "`n" A_ThisHotkey
return

Label3:
 MsgBox,% A_ThisLabel "`n" A_ThisHotkey
return

Label4:
 MsgBox,% A_ThisLabel "`n" A_ThisHotkey
return

Label5:
 MsgBox,% A_ThisLabel "`n" A_ThisHotkey
return
User avatar
evilC
Posts: 4765
Joined: 27 Feb 2014, 12:30

Re: Multiple Dynamic HotKeys in a single ahk file

15 Dec 2017, 07:10

The default AHK hotkey guicontrol pretty lame.
I have written my own system which provides user-defined dynamic hotkeys, will remember the settings between runs (Stores hotkey selection in an INI file) and also allows you to easily add GuiControls whose values are remembered between runs.
See AppFactory

The only real downside is that you need to understand functions and scope in order to use it. An understanding of Bound Functions will also help.
User avatar
Exaskryz
Posts: 2876
Joined: 17 Oct 2015, 20:28

Re: Multiple Dynamic HotKeys in a single ahk file

19 Dec 2017, 17:04

sqlcode wrote:Since I am unable to post screenshot, here is the code. It is almost same as in jaco0646 post which i have mentioned above. I am struggling with how to add respective file path and read them back on.

Code: Select all

#SingleInstance force
#NoEnv
SetBatchLines, -1

#ctrls = 5 ;How many Hotkey controls to add?1
Loop,% #ctrls {
 Gui, Add, Text, xm, Enter Hotkey #%A_Index%:
 IniRead, savedHK%A_Index%, Hotkeys.ini, Hotkeys, %A_Index%, %A_Space%
 IniRead, savedFL%A_Index%, Hotkeys.ini, Hotkeys, %A_Index%, %A_Space%
 If savedHK%A_Index%                                       ;Check for saved hotkeys in INI file.
  Hotkey,% savedHK%A_Index%, Label%A_Index%                 ;Activate saved hotkeys if found.
  Edit,% savedFL%A_Index%, Label%A_Index%
 StringReplace, noMods, savedHK%A_Index%, ~                  ;Remove tilde (~) and Win (#) modifiers...
 StringReplace, noMods, noMods, #,,UseErrorLevel              ;They are incompatible with hotkey controls (cannot be shown).
 Gui, Add, Hotkey, x+5 vHK%A_Index% gGuiLabel, %noMods%        ;Add hotkey controls and show saved hotkeys.
 Gui, Add, Edit, x+5 vMyFile%A_Index%,
 GUI, Add, Button, x+5 vFL%A_Index% gFlLabel, Browse 
}
Gui, Show,,Dynamic Hotkeys
return
GuiClose:
 ExitApp

GuiLabel:

If InStr(%A_GuiControl%,"vk07")            ;vk07 = MenuMaskKey (see below)
  GuiControl,,%A_GuiControl%, % lastHK      ;Reshow the hotkey, because MenuMaskKey clears it.
return

FlLabel:
FileSelectFile,SelectedFile


If SelectedFile
  ;GuiControl,,%A_GuiControl%, % lastHK
  GuiControl,, MyFile%A_Index%, %SelectedFile%
; validateFL(A_GuiControl)
return


validateHK(GuiControl) {
 global lastHK
 Gui, Submit, NoHide
 lastHK := %GuiControl%                     ;Backup the hotkey, in case it needs to be reshown.
 num := SubStr(GuiControl,3)                ;Get the index number of the hotkey control.
 If (HK%num% != "") {                       ;If the hotkey is not blank...
  StringReplace, HK%num%, HK%num%, SC15D, AppsKey      ;Use friendlier names,
  StringReplace, HK%num%, HK%num%, SC154, PrintScreen  ;  instead of these scan codes.
  If CB%num%                                ;  If the 'Win' box is checked, then add its modifier (#).
   HK%num% := "#" HK%num%
  If !RegExMatch(HK%num%,"[#!\^\+]")        ;  If the new hotkey has no modifiers, add the (~) modifier.
   HK%num% := "~" HK%num%                   ;    This prevents any key from being blocked.
  checkDuplicateHK(num)
 }
 If (savedHK%num% || HK%num%)               ;Unless both are empty,
  setHK(num, savedHK%num%, HK%num%)         ;  update INI/GUI
  setFL(num, savedFL%num%, FL%num%)
}
/*
validateFL(GuiControl) {
 global lastFL
 Gui, Submit, NoHide
 lastFL := %GuiControl%                     ;Backup the hotkey, in case it needs to be reshown.
 num := SubStr(GuiControl,3)                ;Get the index number of the hotkey control.
 If (savedFL%num% || FL%num%)               ;Unless both are empty,
  setFL(num, savedFL%num%, FL%num%)         ;  update INI/GUI
}
*/

checkDuplicateHK(num) {
 global #ctrls
 Loop,% #ctrls
  If (HK%num% = savedHK%A_Index%) {
   dup := A_Index
   Loop,6 {
    GuiControl,% "Disable" b:=!b, HK%dup%   ;Flash the original hotkey to alert the user.
    Sleep,200
   }
   GuiControl,,HK%num%,% HK%num% :=""       ;Delete the hotkey and clear the control.
   break
  }
}

setHK(num,INI,GUI) {
 If INI                           ;If previous hotkey exists,
  Hotkey, %INI%, Label%num%, Off  ;  disable it.
 If GUI                           ;If new hotkey exists,
  Hotkey, %GUI%, Label%num%, On   ;  enable it.
 IniWrite,% GUI ? GUI:null, Hotkeys.ini, Hotkeys, %num%
 savedHK%num%  := HK%num%
 TrayTip, Label%num%,% !INI ? GUI " ON":!GUI ? INI " OFF":GUI " ON`n" INI " OFF"
}

setFL(num,INI,GUI) {
 If INI                           ;If previous hotkey exists,
  Hotkey, %INI%, Label%num%, Off  ;  disable it.
 If GUI                           ;If new hotkey exists,
  Hotkey, %GUI%, Label%num%, On   ;  enable it.
 IniWrite,% GUI ? GUI:null, Hotkeys.ini, Hotkeys, %num%
 savedFL%num%  := FL%num%
 TrayTip, Label%num%,% !INI ? GUI " ON":!GUI ? INI " OFF":GUI " ON`n" INI " OFF"
}


#MenuMaskKey vk07                 ;Requires AHK_L 38+
#If ctrl := HotkeyCtrlHasFocus()
 *AppsKey::                       ;Add support for these special keys,
 *BackSpace::                     ;  which the hotkey control does not normally allow.
 *Delete::
 *Enter::
 *Escape::
 *Pause::
 *PrintScreen::
 *Space::
 *Tab::
  modifier := ""
  If GetKeyState("Shift","P")
   modifier .= "+"
  If GetKeyState("Ctrl","P")
   modifier .= "^"
  If GetKeyState("Alt","P")
   modifier .= "!"
  Gui, Submit, NoHide             ;If BackSpace is the first key press, Gui has never been submitted.
  If (A_ThisHotkey == "*BackSpace" && %ctrl% && !modifier)   ;If the control has text but no modifiers held,
   GuiControl,,%ctrl%                                       ;  allow BackSpace to clear that text.
  Else                                                     ;Otherwise,
   GuiControl,,%ctrl%, % modifier SubStr(A_ThisHotkey,2)  ;  show the hotkey.
  validateHK(ctrl)
 return
#If

HotkeyCtrlHasFocus() {
 GuiControlGet, ctrl, Focus       ;ClassNN
 If InStr(ctrl,"hotkey") {
  GuiControlGet, ctrl, FocusV     ;Associated variable
  Return, ctrl
 }
}

;These labels may contain any commands for their respective hotkeys to perform.
Label1:
 MsgBox,% A_ThisLabel "`n" A_ThisHotkey
return
Label2:
 MsgBox,% A_ThisLabel "`n" A_ThisHotkey
return

Label3:
 MsgBox,% A_ThisLabel "`n" A_ThisHotkey
return

Label4:
 MsgBox,% A_ThisLabel "`n" A_ThisHotkey
return

Label5:
 MsgBox,% A_ThisLabel "`n" A_ThisHotkey
return

(I happened to be on vacation when you messaged me for some help. Maybe you don't need this now, but this might shed some light on your situation.)

Code: Select all

FlLabel:
FileSelectFile,SelectedFile


If SelectedFile
  ;GuiControl,,%A_GuiControl%, % lastHK
  GuiControl,, MyFile%A_Index%, %SelectedFile%
; validateFL(A_GuiControl)
return
Look closely at this. There is no Loop. So you don't have any %A_Index% value. I think A_GuiControl is the right approach because your Button GUI, Add, Button, x+5 vFL%A_Index% gFlLabel, Browse should have a name of FL1 or FL2 ... or FL5. You can use SubStr() to take the 3rd and on character from the string "FL___"; you'd want to drop the first 2 instead of capturing the last character because making 10 of these hotkeys would result in a name FL10. You want the 10, not 0. number:=SubStr(A_GuiControl,3) should work, although untested. Then you can use GuiControl,, MyFile%number%, %SelectedFile%, I think.

But I may be misinterpreting the problem, as I only skimmed over the code real quick, and haven't referenced the original code.

Return to “Ask For Help”

Who is online

Users browsing this forum: Bing [Bot], Google [Bot], Jara, lfbender and 229 guests