User defined "Set Hotkeys" Menu (how to?) Topic is solved

Get help with using AutoHotkey (v2 or newer) and its commands and hotkeys
Tobgun1
Posts: 123
Joined: 23 Feb 2023, 07:28

User defined "Set Hotkeys" Menu (how to?)

Post by Tobgun1 » 09 Mar 2023, 13:33

:superhappy:

Heyyy,
As I keep learning: "New Day! New Task!" :)

I got several hotkeys in my script.
Like F7 , F8, F9 and F10

In this example F10 is ExitApp

How could I remap them in a easy way, for users that dont understand AHK?

Like something that starts on the first time , asks for hotkeys for function a, wich one for function b and so on

I read GUI is the way to go for it.


But probably someone got some nice ideas or a hint where to go for....

Like a key press F1 then a window popping up and asks for the keys step by step, and safes it for all time.

So only f1 stays binded if the user want to re-do em

Thanks for reading this and would be nice if I get some ideas together here

😂🙈🤷🏻‍♂️
Last edited by Tobgun1 on 13 Mar 2023, 17:11, edited 1 time in total.

User avatar
mikeyww
Posts: 26596
Joined: 09 Sep 2014, 18:38

Re: User defined remap of Hotkeys (how to?)

Post by mikeyww » 09 Mar 2023, 15:02

The question isn't how to specify a hotkey-- use a GUI hotkey control-- but how to specify the actions to be executed. I think that some "exec" scripts are already posted. Alternatively, they could be dumped into a script file and executed there. But gee, it seems a lot faster just to write a hotkey subroutine!

If the user doesn't understand AutoHotkey, then it seems like you are looking at a chatbot that can convert a narrative description into a computer program. Microsoft already did that (and not so well, it seems)!

User avatar
Datapoint
Posts: 294
Joined: 18 Mar 2018, 17:06

Re: User defined remap of Hotkeys (how to?)

Post by Datapoint » 09 Mar 2023, 16:06

If I understand correctly, I think something like this may work.
(At the moment it doesn't turn off existing hotkeys if you change them, but this might give you an idea of what I am suggesting.)

Code: Select all

#Requires AutoHotkey v2

A_TrayMenu.Add("Set Hotkeys", SetHotkeys) ; Add a tray menu item to change hotkeys

; Create GUI
MyGui := Gui(, "Set Hotkeys")
MyGui.Add("Hotkey", "vChosenHotkey")
MyGui.Add("Button", "Default", "OK").OnEvent("Click", OK_Click)

; Read stored hotkeys (if they exist) from Hotkeys.ini
XXHK := IniRead(A_ScriptDir "\Hotkeys.ini", "Hotkeys", "XXHotkey")
if XXHK = ""
	SetHotkeys()
else
	Hotkey XXHK, DoXX
return

F10::ExitApp

SetHotkeys(*)
{
	MyGui.Show()
}

OK_Click(*)
{
    Saved := MyGui.Submit()
	Hotkey Saved.ChosenHotkey, DoXX
	IniWrite Saved.ChosenHotkey, A_ScriptDir "\Hotkeys.ini", "Hotkeys", "XXHotkey"
}

DoXX(*)
{
	MsgBox "XX"
}

/* Example Hotkeys.ini file contents:

[Hotkeys]
XXHotkey=F6

User avatar
DuckingQuack
Posts: 219
Joined: 20 Jan 2023, 18:20

Re: User defined remap of Hotkeys (how to?)

Post by DuckingQuack » 10 Mar 2023, 06:04

mikeyww wrote:
09 Mar 2023, 15:02
The question isn't how to specify a hotkey-- use a GUI hotkey control-- but how to specify the actions to be executed.
Is this what you mean?
https://www.autohotkey.com/docs/v2/lib/Hotkey.htm#ExampleIfFn
mikeyww wrote:
09 Mar 2023, 15:02
If the user doesn't understand AutoHotkey
I believe he intends to disseminate his script and as a result, have end-users who will not be able to use ahk but still wants them to be able to set the hotkeys for the functions of the script as a convenience to the user.
Best of Luck,
The Duck

User avatar
mikeyww
Posts: 26596
Joined: 09 Sep 2014, 18:38

Re: User defined remap of Hotkeys (how to?)

Post by mikeyww » 10 Mar 2023, 06:48

Thanks for clarifying that. One easy approach for a fixed number of subroutines could be adding a listbox or dropdown control that shows a name for each. This would enable the user to map a hotkey to any of them.

Tobgun1
Posts: 123
Joined: 23 Feb 2023, 07:28

Re: User defined remap of Hotkeys (how to?)

Post by Tobgun1 » 10 Mar 2023, 09:02

I believe he intends to disseminate his script and as a result, have end-users who will not be able to use ahk but still wants them to be able to set the hotkeys for the functions of the script as a convenience to the user.
Hey @mikeyww , @Datapoint and @DuckingQuack ,
Thanks for your answers :)
I am sorry if I am hard to understand. My english is just base English and I sometimes mix it up 😅🙈

DuckingQuack understood my question.
I had no time yet to check Datapoints message and script part.

I usually try an easy way to let my "users" (mostly friends), change the Hotkey of the Function I created.

So like if I have F10 for exit app I try to let the user choose wich key he wants for the ExitApp command (or function)

Mikeyww's last answer sounds good I check hotkey subroutines and the script part from Datapoint later 😅👍

User avatar
mikeyww
Posts: 26596
Joined: 09 Sep 2014, 18:38

Re: User defined remap of Hotkeys (how to?)

Post by mikeyww » 10 Mar 2023, 09:18

Code: Select all

#Requires AutoHotkey v2
gui1 := Gui(, 'Set Hotkeys')
gui1.SetFont('s10')
hk   := gui1.AddHotkey('w104')
fn   := gui1.AddDDL('wp x+m Choose1', ['a', 'b'])
gui1.AddButton('xm w224 Default', 'OK').OnEvent('Click', OK_Click)
gui1.Show('w250')

OK_Click(*) {
 gui1.Submit
 Hotkey hk.Value, %fn.Text%, 'On'
 SoundBeep 1500
}

a(ThisHotkey) {
 MsgBox ThisHotkey, 'Hotkey triggered', 64
}

User avatar
Datapoint
Posts: 294
Joined: 18 Mar 2018, 17:06

Re: User defined remap of Hotkeys (how to?)

Post by Datapoint » 10 Mar 2023, 11:24

Tobgun1 wrote:
10 Mar 2023, 09:02
I am sorry if I am hard to understand. My english is just base English and I sometimes mix it up 😅🙈

DuckingQuack understood my question.
I had no time yet to check Datapoints message and script part.
I thought your question was OK, and I understood your question the same way that DuckingQuack paraphrased.

So my script should give you a start. It allows you to assign a hotkey to the DoXX() function. The hotkeys are stored in a separate file (Hotkeys.ini) and that file should be located in the same folder as the script itself. When the script starts, if Hotkeys.ini does not have a hotkey stored then it opens the GUI where the user can press a hotkey and then press OK to save the hotkey. If a hotkey is already assigned, you can right-click the tray menu and select "Set Hotkeys" to show the GUI again.

When you select a new hotkey, it doesn't turn off the old hotkey so pressing both the new and old hotkey will trigger DoXX(). You could disable the old hotkey using the hotkey function or just reload the script.

User avatar
DuckingQuack
Posts: 219
Joined: 20 Jan 2023, 18:20

Re: User defined remap of Hotkeys (how to?)

Post by DuckingQuack » 10 Mar 2023, 12:11

@Datapoint
Maybe an automatic reload upon assigning a hotkey would solve the double hotkey issue when reassigning them?… it’s a somewhat barbaric solution, but i would expect it to work.
Best of Luck,
The Duck

Tobgun1
Posts: 123
Joined: 23 Feb 2023, 07:28

Re: User defined remap of Hotkeys (how to?)

Post by Tobgun1 » 11 Mar 2023, 07:14

Datapoint wrote:
10 Mar 2023, 11:24
Tobgun1 wrote:
10 Mar 2023, 09:02
I am sorry if I am hard to understand. My english is just base English and I sometimes mix it up 😅🙈

DuckingQuack understood my question.
I had no time yet to check Datapoints message and script part.
I thought your question was OK, and I understood your question the same way that DuckingQuack paraphrased.

So my script should give you a start. It allows you to assign a hotkey to the DoXX() function. The hotkeys are stored in a separate file (Hotkeys.ini) and that file should be located in the same folder as the script itself. When the script starts, if Hotkeys.ini does not have a hotkey stored then it opens the GUI where the user can press a hotkey and then press OK to save the hotkey. If a hotkey is already assigned, you can right-click the tray menu and select "Set Hotkeys" to show the GUI again.

When you select a new hotkey, it doesn't turn off the old hotkey so pressing both the new and old hotkey will trigger DoXX(). You could disable the old hotkey using the hotkey function or just reload the script.
Thanks for answering 😊

So DoXX is your UDF? Function ?
But when and how do I create that ini file?
Does it creates it or saves into it after it is done?

So the "user " can select hes hotkeys, and use it once with double hotkeys , and after it is once exitapp and restart it the ini saves hes last hotkeys in it?

Sorry I am asking this without trying much. I had a long week and did sleep now 12 hours while 14 hours in bed 🤓😂🙈

If you mind not answering because I didnt try it yet I have no problem with 😅

User avatar
Datapoint
Posts: 294
Joined: 18 Mar 2018, 17:06

Re: User defined remap of Hotkeys (how to?)

Post by Datapoint » 11 Mar 2023, 12:16

You can create the hotkeys.ini file yourself.
Right-click -> New -> Text Document
Rename "New Text Document.txt" to "Hotkeys.ini"
Open Hotkeys.ini and paste this text into it:

Code: Select all

[Hotkeys]
XXHotkey=
Save and close, then run the script.
Last edited by Datapoint on 11 Mar 2023, 12:17, edited 1 time in total.

Tobgun1
Posts: 123
Joined: 23 Feb 2023, 07:28

Re: User defined remap of Hotkeys (how to?)

Post by Tobgun1 » 11 Mar 2023, 17:53

Datapoint wrote:
11 Mar 2023, 12:16
You can create the hotkeys.ini file yourself.
Right-click -> New -> Text Document
Rename "New Text Document.txt" to "Hotkeys.ini"
Open Hotkeys.ini and paste this text into it:

Code: Select all

[Hotkeys]
XXHotkey=
Save and close, then run the script.
Hey :) thanks for all those answers!

@mikeyww i could not adapt ur answer yet, i have 2 functions to choose but can only register to one Hotkey one of the functions yet

Code: Select all

#Requires AutoHotkey v2
gui1 := Gui(, 'Set Hotkeys')
gui1.SetFont('s10')
hk   := gui1.AddHotkey('w104')
fn   := gui1.AddDDL('wp x+m Choose1', ['a', 'b'])
gui1.AddButton('xm w224 Default', 'OK').OnEvent('Click', OK_Click)
gui1.Show('w250')

OK_Click(*) {
 gui1.Submit
 Hotkey hk.Value, %fn.Text%, 'On'
 SoundBeep 1500
}

a(ThisHotkey) {
    Static on := false
    If on := !on {
        MsgBox "Function A On"
    } Else {
        Nachrichten
    }
}
b(ThisHotkey) {
    Static on := false
    If on := !on {
        MsgBox "Function B On"
    } Else {
        Nachrichten2
    }
   }




Nachrichten() {
    MsgBox "Function A Off"
}
Nachrichten2() {
    MsgBox "Function B Off"
}

; Hotkey Set Code by Mikeyww

@Datapoint

atm i like yours more, and could adapt it, and saved somehow 2 Hotkeys into 2 Functions BUT, i had to delete the "return" , run it again and then insert the return and run it once again :D
i know people would like it more that i understand what i am doing here, BUT, well, this Hotkey change seems to be a big thing and as i see MANY lines of code to understand :crazy:

here is the actuall verion, where i integreated message boxes as "Function A and B" to try to understand how and where to add, and what is happening,
btw i found out i did a Hotkey.ini text file then added your text, but i did not save it after as .ini

so for me severall hours went for those small changes :D

if you might give me an answer for more understanding of the code would be nice

Thanks for your time! Tobgun1

Code: Select all

#Requires AutoHotkey v2

A_TrayMenu.Add("Set Hotkeys", SetHotkeys) ; Add a tray menu item to change hotkeys

; Create GUI
MyGui := Gui(, "Set Hotkeys")
MyGui.Add("Hotkey", "vChosenHotkey")
MyGui.Add("Button", "Default", "OK").OnEvent("Click", OK_Click)

; Read stored hotkeys (if they exist) from Hotkeys.ini
XXHK := IniRead(A_ScriptDir "\Hotkeys.ini", "Hotkeys", "XXHotkey")
if XXHK = ""
	SetHotkeys()
else
	Hotkey XXHK, TestFunctionA
return ; <<<<-------------------------------------------------------------------------- If i delete this return i can safe Hotkey 2 for TestFunctionB
XXHK := IniRead(A_ScriptDir "\Hotkeys.ini", "Hotkeys", "XXHotkey")
if XXHK = ""
	SetHotkeys()
else
	Hotkey XXHK, TestFunctionB
return


F10::ExitApp

SetHotkeys(*)
{
	MyGui.Show()
}

OK_Click(*)
{
    Saved := MyGui.Submit()
	Hotkey Saved.ChosenHotkey, TestFunctionA
	Hotkey Saved.ChosenHotkey, TestFunctionB
	IniWrite Saved.ChosenHotkey, A_ScriptDir "\Hotkeys.ini", "Hotkeys", "XXHotkey"
}

TestFunctionA(*) {
    Static on := false
    If on := !on {
        MsgBox "funktion A on"
    } Else {
        Nachrichten
    }
}
TestFunctionB(*) {
    Static on := false
    If on := !on {
        MsgBox "funktion B on"
    } Else {
        Nachrichten2
    }
}

Nachrichten() {
    MsgBox "funktion A off"
}
Nachrichten2() {
    MsgBox "funktion B off"
}
/* Example Hotkeys.ini file contents:

[Hotkeys]
XXHotkey=

; Hotkey Set Code by Datapoint

User avatar
Datapoint
Posts: 294
Joined: 18 Mar 2018, 17:06

Re: User defined remap of Hotkeys (how to?)  Topic is solved

Post by Datapoint » 12 Mar 2023, 01:28

Try this.
(You will need to modify the INI file - see the text at the end of the script)

Code: Select all

#Requires AutoHotkey v2

; Add a tray menu item to change hotkeys
A_TrayMenu.Add("Set Hotkeys", SetHotkeys)

; Read saved hotkeys
FunctionAHotkey  := IniRead(A_ScriptDir "\Hotkeys.ini", "Hotkeys", "TFA_Hotkey")
FunctionBHotkey  := IniRead(A_ScriptDir "\Hotkeys.ini", "Hotkeys", "TFB_Hotkey")
ExitScriptHotkey := IniRead(A_ScriptDir "\Hotkeys.ini", "Hotkeys", "Exit_Hotkey")

; Create GUI
MyGui := Gui(, "Set Hotkeys")

MyGui.AddText("x10", "Function A Hotkey")
MyGui.AddHotkey("x+10 vTestFunctionAHotkey", FunctionAHotkey)

MyGui.AddText("x10", "Function B Hotkey")
MyGui.AddHotkey("x+10 vTestFunctionBHotkey", FunctionBHotkey)

MyGui.AddText("x10", "Exit Script")
MyGui.AddHotkey("x+10 vExitScriptHotkey", ExitScriptHotkey)

MyGui.Add("Button", "Default x10 w100", "OK").OnEvent("Click", OK_Click)

; If a hotkey is blank show the GUI, else create saved hotkeys
if FunctionAHotkey = "" || FunctionBHotkey = "" || ExitScriptHotkey = ""
	SetHotkeys()
else
{
	Hotkey FunctionAHotkey, TestFunctionA
	Hotkey FunctionBHotkey, TestFunctionB
	Hotkey ExitScriptHotkey, ExitScript
}
return

SetHotkeys(*)
{
	MyGui.Show()
}

OK_Click(*)
{
    Saved := MyGui.Submit()
	Hotkey Saved.TestFunctionAHotkey, TestFunctionA
	Hotkey Saved.TestFunctionBHotkey, TestFunctionB
	Hotkey Saved.ExitScriptHotkey, ExitScript
	IniWrite Saved.TestFunctionAHotkey, A_ScriptDir "\Hotkeys.ini", "Hotkeys", "TFA_Hotkey"
	IniWrite Saved.TestFunctionBHotkey, A_ScriptDir "\Hotkeys.ini", "Hotkeys", "TFB_Hotkey"
	IniWrite Saved.ExitScriptHotkey, A_ScriptDir "\Hotkeys.ini", "Hotkeys", "Exit_Hotkey"
	Reload
}

TestFunctionA(*) {
    Static on := false
    If on := !on {
        MsgBox "funktion A on"
    } Else {
        Nachrichten()
    }
}

TestFunctionB(*) {
    Static on := false
    If on := !on {
        MsgBox "funktion B on"
    } Else {
        Nachrichten2()
    }
}


Nachrichten() {
    MsgBox "funktion A off"
}

Nachrichten2() {
    MsgBox "funktion B off"
}

ExitScript(*)
{
	ExitApp
}

/* Example Hotkeys.ini file contents:

[Hotkeys]
TFA_Hotkey=
TFB_Hotkey=
Exit_Hotkey=

Or this, which is similar to the above, but it uses objects, and loops to keep track of the functions / hotkeys / gui elements. This will be easier to manage if you have a lot of items.
This version also turns off old hotkeys when new hotkeys are set, instead of reloading the script like the above example does.

Code: Select all

#Requires AutoHotkey v2

; Add a tray menu item to change hotkeys
A_TrayMenu.Add("Set Hotkeys", SetHotkeys)

; Use this data to keep track of each hotkey / function / GUI info
SavedHotkeys := []
SavedHotkeys.Push( {Function:   TestFunctionA
                  , INI_Key:    "TFA_Hotkey"
                  , GUI_Text:   "Function A Hotkey"
                  , GUI_Var:    "TFA"} )

SavedHotkeys.Push( {Function:   TestFunctionB
                  , INI_Key:    "TFB_Hotkey"
                  , GUI_Text:   "Function B Hotkey"
                  , GUI_Var:    "TFB"} )

SavedHotkeys.Push( {Function:   ExitScript
                  , INI_Key:    "Exit_Hotkey"
                  , GUI_Text:   "Exit Script"
                  , GUI_Var:    "SC_Exit"} )

; Create a GUI
MyGui := Gui(, "Set Hotkeys")

HK_NOT_SET := false

; Read saved hotkeys
for i, MyHotkey in SavedHotkeys
{
    MyHotkey.AssignedKey := IniRead(A_ScriptDir "\Hotkeys.ini", "Hotkeys", MyHotkey.INI_Key)

    MyGui.AddText("x10", MyHotkey.GUI_Text)
    MyGui.AddHotkey("x+10 v"  MyHotkey.GUI_Var, MyHotkey.AssignedKey)

    ; If there is a blank hotkey then set HK_NOT_SET to true so the GUI will be opened later
    if MyHotkey.AssignedKey = ""
        HK_NOT_SET := true
    ; else activate the saved hotkey
    else
        Hotkey MyHotkey.AssignedKey, MyHotkey.Function
}

MyGui.Add("Button", "Default x10 w100", "OK").OnEvent("Click", OK_Click)

; Open the GUI if there was a blank hotkey loaded from the INI
if HK_NOT_SET
    SetHotkeys()
return

SetHotkeys(*)
{
    MyGui.Show()
}

OK_Click(*)
{
    ; Disable old hotkeys
    for i, MyHotkey in SavedHotkeys
        if MyHotkey.AssignedKey != ""
            Hotkey MyHotkey.AssignedKey, "Off"
    Saved := MyGui.Submit()
    ; Enable new hotkeys and save to INI
    for i, MyHotkey in SavedHotkeys
    {
        MyHotkey.AssignedKey := Saved.%MyHotkey.GUI_Var%
        Hotkey MyHotkey.AssignedKey, MyHotkey.Function
        IniWrite MyHotkey.AssignedKey, A_ScriptDir "\Hotkeys.ini", "Hotkeys", MyHotkey.INI_Key
    }
}

TestFunctionA(*) {
    Static on := false
    If on := !on {
        MsgBox "funktion A on"
    } Else {
        Nachrichten()
    }
}

TestFunctionB(*) {
    Static on := false
    If on := !on {
        MsgBox "funktion B on"
    } Else {
        Nachrichten2()
    }
}

Nachrichten() {
    MsgBox "funktion A off"
}

Nachrichten2() {
    MsgBox "funktion B off"
}

ExitScript(*)
{
    ExitApp
}

/* Example Hotkeys.ini file contents:

[Hotkeys]
TFA_Hotkey=
TFB_Hotkey=
Exit_Hotkey=


Tobgun1
Posts: 123
Joined: 23 Feb 2023, 07:28

Re: User defined remap of Hotkeys (how to?)

Post by Tobgun1 » 12 Mar 2023, 13:29

Datapoint wrote:
12 Mar 2023, 01:28
Try this.
(You will need to modify the INI file - see the text at the end of the script)

Code: Select all

#Requires AutoHotkey v2

; Add a tray menu item to change hotkeys
A_TrayMenu.Add("Set Hotkeys", SetHotkeys)

; Read saved hotkeys
FunctionAHotkey  := IniRead(A_ScriptDir "\Hotkeys.ini", "Hotkeys", "TFA_Hotkey")
FunctionBHotkey  := IniRead(A_ScriptDir "\Hotkeys.ini", "Hotkeys", "TFB_Hotkey")
ExitScriptHotkey := IniRead(A_ScriptDir "\Hotkeys.ini", "Hotkeys", "Exit_Hotkey")

; Create GUI
MyGui := Gui(, "Set Hotkeys")

MyGui.AddText("x10", "Function A Hotkey")
MyGui.AddHotkey("x+10 vTestFunctionAHotkey", FunctionAHotkey)

MyGui.AddText("x10", "Function B Hotkey")
MyGui.AddHotkey("x+10 vTestFunctionBHotkey", FunctionBHotkey)

MyGui.AddText("x10", "Exit Script")
MyGui.AddHotkey("x+10 vExitScriptHotkey", ExitScriptHotkey)

MyGui.Add("Button", "Default x10 w100", "OK").OnEvent("Click", OK_Click)

; If a hotkey is blank show the GUI, else create saved hotkeys
if FunctionAHotkey = "" || FunctionBHotkey = "" || ExitScriptHotkey = ""
	SetHotkeys()
else
{
	Hotkey FunctionAHotkey, TestFunctionA
	Hotkey FunctionBHotkey, TestFunctionB
	Hotkey ExitScriptHotkey, ExitScript
}
return

SetHotkeys(*)
{
	MyGui.Show()
}

OK_Click(*)
{
    Saved := MyGui.Submit()
	Hotkey Saved.TestFunctionAHotkey, TestFunctionA
	Hotkey Saved.TestFunctionBHotkey, TestFunctionB
	Hotkey Saved.ExitScriptHotkey, ExitScript
	IniWrite Saved.TestFunctionAHotkey, A_ScriptDir "\Hotkeys.ini", "Hotkeys", "TFA_Hotkey"
	IniWrite Saved.TestFunctionBHotkey, A_ScriptDir "\Hotkeys.ini", "Hotkeys", "TFB_Hotkey"
	IniWrite Saved.ExitScriptHotkey, A_ScriptDir "\Hotkeys.ini", "Hotkeys", "Exit_Hotkey"
	Reload
}

TestFunctionA(*) {
    Static on := false
    If on := !on {
        MsgBox "funktion A on"
    } Else {
        Nachrichten()
    }
}

TestFunctionB(*) {
    Static on := false
    If on := !on {
        MsgBox "funktion B on"
    } Else {
        Nachrichten2()
    }
}


Nachrichten() {
    MsgBox "funktion A off"
}

Nachrichten2() {
    MsgBox "funktion B off"
}

ExitScript(*)
{
	ExitApp
}

/* Example Hotkeys.ini file contents:

[Hotkeys]
TFA_Hotkey=
TFB_Hotkey=
Exit_Hotkey=

Or this, which is similar to the above, but it uses objects, and loops to keep track of the functions / hotkeys / gui elements. This will be easier to manage if you have a lot of items.
This version also turns off old hotkeys when new hotkeys are set, instead of reloading the script like the above example does.

Code: Select all

#Requires AutoHotkey v2

; Add a tray menu item to change hotkeys
A_TrayMenu.Add("Set Hotkeys", SetHotkeys)

; Use this data to keep track of each hotkey / function / GUI info
SavedHotkeys := []
SavedHotkeys.Push( {Function:   TestFunctionA
                  , INI_Key:    "TFA_Hotkey"
                  , GUI_Text:   "Function A Hotkey"
                  , GUI_Var:    "TFA"} )

SavedHotkeys.Push( {Function:   TestFunctionB
                  , INI_Key:    "TFB_Hotkey"
                  , GUI_Text:   "Function B Hotkey"
                  , GUI_Var:    "TFB"} )

SavedHotkeys.Push( {Function:   ExitScript
                  , INI_Key:    "Exit_Hotkey"
                  , GUI_Text:   "Exit Script"
                  , GUI_Var:    "SC_Exit"} )

; Create a GUI
MyGui := Gui(, "Set Hotkeys")

HK_NOT_SET := false

; Read saved hotkeys
for i, MyHotkey in SavedHotkeys
{
    MyHotkey.AssignedKey := IniRead(A_ScriptDir "\Hotkeys.ini", "Hotkeys", MyHotkey.INI_Key)

    MyGui.AddText("x10", MyHotkey.GUI_Text)
    MyGui.AddHotkey("x+10 v"  MyHotkey.GUI_Var, MyHotkey.AssignedKey)

    ; If there is a blank hotkey then set HK_NOT_SET to true so the GUI will be opened later
    if MyHotkey.AssignedKey = ""
        HK_NOT_SET := true
    ; else activate the saved hotkey
    else
        Hotkey MyHotkey.AssignedKey, MyHotkey.Function
}

MyGui.Add("Button", "Default x10 w100", "OK").OnEvent("Click", OK_Click)

; Open the GUI if there was a blank hotkey loaded from the INI
if HK_NOT_SET
    SetHotkeys()
return

SetHotkeys(*)
{
    MyGui.Show()
}

OK_Click(*)
{
    ; Disable old hotkeys
    for i, MyHotkey in SavedHotkeys
        if MyHotkey.AssignedKey != ""
            Hotkey MyHotkey.AssignedKey, "Off"
    Saved := MyGui.Submit()
    ; Enable new hotkeys and save to INI
    for i, MyHotkey in SavedHotkeys
    {
        MyHotkey.AssignedKey := Saved.%MyHotkey.GUI_Var%
        Hotkey MyHotkey.AssignedKey, MyHotkey.Function
        IniWrite MyHotkey.AssignedKey, A_ScriptDir "\Hotkeys.ini", "Hotkeys", MyHotkey.INI_Key
    }
}

TestFunctionA(*) {
    Static on := false
    If on := !on {
        MsgBox "funktion A on"
    } Else {
        Nachrichten()
    }
}

TestFunctionB(*) {
    Static on := false
    If on := !on {
        MsgBox "funktion B on"
    } Else {
        Nachrichten2()
    }
}

Nachrichten() {
    MsgBox "funktion A off"
}

Nachrichten2() {
    MsgBox "funktion B off"
}

ExitScript(*)
{
    ExitApp
}

/* Example Hotkeys.ini file contents:

[Hotkeys]
TFA_Hotkey=
TFB_Hotkey=
Exit_Hotkey=


OH MY GOSH :o :shock:
i am amazed! :superhappy:

THANK YOU VERY MUCH! for the FULL SOLUTION!
and thank you for sharing your Code with me!
cant tell you how happy i am :)

i try the next ongoing days to understand more of it and adapt it into my Script!

that was now a 120% Solution :D , more then i suspected to get!

Thanks Tobgun1

Tobgun1
Posts: 123
Joined: 23 Feb 2023, 07:28

Re: User defined "Set Hotkeys" Menu (how to?)

Post by Tobgun1 » 29 Mar 2023, 19:47

:bravo: @Datapoint , i wanna thank you once more now :D
some days have gone and i am still Happy!! that u shared this work with me! :)

:dance:

May i ask you, i got a if GetKeyState("LButton", "P") inside my script, is it possible to make this key a "Hotkey" wich i can change?
like if i got if GetKeyState("LButton", "P") to make it if GetKeyState("Button the User chooses", "P") ? Especially maybe a Mouse Button? Cuse your GUI just accepts Keyboard Keys when i tried it out.

Greetings your Happy "Hotkey-Set Code" user :D

User avatar
Datapoint
Posts: 294
Joined: 18 Mar 2018, 17:06

Re: User defined "Set Hotkeys" Menu (how to?)

Post by Datapoint » 30 Mar 2023, 13:41

You could use a gui control other than the hotkey control. Like maybe some radio buttons, or a dropdown list to select the mouse hotkey.

I don't know much about your question, but I did a quick search and found some custom hotkeys controls written for older versions of AHK. But I would still suggest just using radio buttons or a DDL.
https://www.autohotkey.com/board/topic/9460-an-alternative-to-gui-add-hotkey/
https://www.autohotkey.com/board/topic/5288-custom-hotkey-control/
https://www.autohotkey.com/board/topic/9522-hotkey-control-and-mouse-buttons/

Tobgun1
Posts: 123
Joined: 23 Feb 2023, 07:28

Re: User defined "Set Hotkeys" Menu (how to?)

Post by Tobgun1 » 31 Mar 2023, 05:26

Datapoint wrote:
30 Mar 2023, 13:41
You could use a gui control other than the hotkey control. Like maybe some radio buttons, or a dropdown list to select the mouse hotkey.

I don't know much about your question, but I did a quick search and found some custom hotkeys controls written for older versions of AHK. But I would still suggest just using radio buttons or a DDL.
https://www.autohotkey.com/board/topic/9460-an-alternative-to-gui-add-hotkey/
https://www.autohotkey.com/board/topic/5288-custom-hotkey-control/
https://www.autohotkey.com/board/topic/9522-hotkey-control-and-mouse-buttons/
Hey thanks for another response ✌😀
I try to read and understand them but it most of the time feels like high mathematics for me 😂🙈

I use AHKv2 and it is quite hard for me to adapt things from v1 to v2

I think I might try those v1 stuff but then I have the problem to have your v2 stuff in my v2 script.

I think I get overflowed by to much complex english to understand what a going on hahaha

So thanks again for your time and once more

Thanks for that great Set Hotkey part !! I still like it!! Very nice work and since I know how to use it it was a joy for me to adapt it to several more functions 😀👍🔥

User avatar
Datapoint
Posts: 294
Joined: 18 Mar 2018, 17:06

Re: User defined "Set Hotkeys" Menu (how to?)

Post by Datapoint » 31 Mar 2023, 12:44

Tobgun1 wrote:
31 Mar 2023, 05:26
I try to read and understand them but it most of the time feels like high mathematics for me 😂🙈

I use AHKv2 and it is quite hard for me to adapt things from v1 to v2

I think I might try those v1 stuff but then I have the problem to have your v2 stuff in my v2 script.
You don't need to use the examples I linked to. I provided the link mostly to show context and that it is a complex question, and others have dealt with this issue before.

My other suggestion was to add another type of GUI control. The following example uses a DropDownList to select the mouse hotkey. Then when you press Ctrl + the mouse key, it runs TestFunctionC.

Code: Select all

#Requires AutoHotkey v2

; Add a tray menu item to change hotkeys
A_TrayMenu.Add("Set Hotkeys", SetHotkeys)

; Use this data to keep track of each hotkey / function / GUI info
SavedHotkeys := []
SavedHotkeys.Push( {Function:		TestFunctionA
                  , INI_Key:		"TFA_Hotkey"
                  , GUI_Text:		"Function A Hotkey"
                  , GUI_CtrlObj:	"" ; Changed to use GUI Control Object instead of GUI Var https://www.autohotkey.com/docs/v2/lib/GuiControl.htm
                  , AssignedKey:	""} ) ; AssignedKey will be read from INI or set by GUI

SavedHotkeys.Push( {Function:		TestFunctionB
                  , INI_Key:		"TFB_Hotkey"
                  , GUI_Text:		"Function B Hotkey"
                  , GUI_CtrlObj:	""
                  , AssignedKey:	""} )

SavedHotkeys.Push( {Function:		ExitScript
                  , INI_Key:		"Exit_Hotkey"
                  , GUI_Text:		"Exit Script"
                  , GUI_CtrlObj:	""
                  , AssignedKey:	""} )

; Create a GUI
MyGui := Gui(, "Set Hotkeys")

HK_NOT_SET := false

; Read saved hotkeys
for i, MyHotkey in SavedHotkeys
{
    MyHotkey.AssignedKey := IniRead(A_ScriptDir "\Hotkeys.ini", "Hotkeys", MyHotkey.INI_Key)

    MyGui.AddText("x10 w150", MyHotkey.GUI_Text)
    MyHotkey.GUI_CtrlObj := MyGui.AddHotkey("x+10 w130", MyHotkey.AssignedKey)

    ; If there is a blank hotkey then set HK_NOT_SET to true so the GUI will be opened later
    if MyHotkey.AssignedKey = ""
        HK_NOT_SET := true
    ; else activate the saved hotkey
    else
        Hotkey MyHotkey.AssignedKey, MyHotkey.Function, "On"
}

; Turn on mouse hotkey (Ctrl + Mousekey)
MouseDDLSelection := IniRead(A_ScriptDir "\Hotkeys.ini", "Hotkeys", "MouseKey")
MyGui.AddText("x10 w150", "Function C Hotkey (Ctrl + MouseKey)")
Mouse_DDL_CtrlObj := MyGui.AddDropDownList("x+10 w130 Choose" MouseDDLSelection, ["LButton","RButton","MButton", "XButton1", "XButton2"])
MouseHotkey := "^" Mouse_DDL_CtrlObj.Text
if Mouse_DDL_CtrlObj.Text
    Hotkey MouseHotkey, TestFunctionC

MyGui.AddButton("Default y+10 w130", "OK").OnEvent("Click", OK_Click)

; Open the GUI if there was a blank hotkey loaded from the INI
if HK_NOT_SET || !Mouse_DDL_CtrlObj.Text
    SetHotkeys()
return

SetHotkeys(*)
{
    MyGui.Show()
}

OK_Click(*)
{
    global

    ; Disable old hotkeys
    for i, MyHotkey in SavedHotkeys
    {
        if MyHotkey.AssignedKey != ""
            Hotkey MyHotkey.AssignedKey, "Off"
    }
    if MouseHotkey != "^"
        Hotkey MouseHotkey, "Off"

    ; Enable new hotkeys and save to INI
    MyGui.Submit()
    for i, MyHotkey in SavedHotkeys
    {
        MyHotkey.AssignedKey := MyHotkey.GUI_CtrlObj.Value
        if MyHotkey.AssignedKey = ""
            continue
        Hotkey MyHotkey.AssignedKey, MyHotkey.Function, "On"
        IniWrite MyHotkey.AssignedKey, A_ScriptDir "\Hotkeys.ini", "Hotkeys", MyHotkey.INI_Key
    }

    ; Enable mouse hotkey and write to INI
    if Mouse_DDL_CtrlObj.Value
    {
        IniWrite Mouse_DDL_CtrlObj.Value, A_ScriptDir "\Hotkeys.ini", "Hotkeys", "MouseKey"
        MouseHotkey := "^" Mouse_DDL_CtrlObj.Text ; Ctrl + Mouse Hotkey
        Hotkey MouseHotkey, TestFunctionC, "On"
    }

}

TestFunctionA(*)
{
    MsgBox "Function A"
}

TestFunctionB(*)
{
    MsgBox "Function B"
}

TestFunctionC(*)
{
    while GetKeyState(Mouse_DDL_CtrlObj.Text, "P")
        ToolTip(A_Index), Sleep(20)
    ToolTip
}

ExitScript(*)
{
    ExitApp
}


/* Example Hotkeys.ini file contents:

[Hotkeys]
TFA_Hotkey=
TFB_Hotkey=
Exit_Hotkey=
MouseKey=

Tobgun1
Posts: 123
Joined: 23 Feb 2023, 07:28

Re: User defined "Set Hotkeys" Menu (how to?)

Post by Tobgun1 » 22 Apr 2023, 08:39

@Datapoint
Hello. I actually struggle because of a script function.

It sends shift down. And I cant push the F Keys hotkeys anymore because of the shift + hotkey. How do I add the * to ignore the shift ?
Like *F5 works.
But object(*)
Hotkey ini F5. How do I re write this ?

User avatar
Datapoint
Posts: 294
Joined: 18 Mar 2018, 17:06

Re: User defined "Set Hotkeys" Menu (how to?)

Post by Datapoint » 23 Apr 2023, 12:57

Try adding "*" when calling the hotkey function.

Code: Select all

StoredHotkey := "F5"
Hotkey "*" StoredHotkey , FunctionName, "On"

Post Reply

Return to “Ask for Help (v2)”