Why does remapping key interfere with FormatTime? - autohotkey

I have this code:
FormatTime, CurrentYearMonth,, yyyy-MM
MsgBox, %CurrentYearMonth%
f3::Run D:\folders\%CurrentYearMonth%
a::a
Pressing F3 only opens D:\folders, and there is no message pops up. In order to make it work properly, I need to use
#InputLevel 1
FormatTime, CurrentYearMonth,, yyyy-MM
MsgBox, %CurrentYearMonth%
f3::Run D:\folders\%CurrentYearMonth%
#InputLevel 0
a::a
But I don't understand why this should be the case. I read about #InputLevel and SendLevel but I don't understand much. Do you know why?

I suspect your code is after the top auto-execute section of your script, this will mean your F3 hotkey (f3::) will execute only that line and %CurrentYearMonth% will not be populated. You could format your code like this,
f3::
FormatTime, CurrentYearMonth,, yyyy-MM
MsgBox, %CurrentYearMonth%
Run D:\folders\%CurrentYearMonth%
return
F3 will run all the code from f3:: until return. This is easier to read and understand.
More details on return - https://www.autohotkey.com/docs/commands/Return.htm

Related

Mapping the Excel F2 to a different button does not work when F2 is re-mapped to open and application

I mapped {F2} to open/start "OneNote"
I want to use the XButton2 to take the function of F2 when Excel is the active application.
However, pressing of the XButton2 always activtates OneNote.
I tried everything to make this work.
F2::
IF WinExist("ahk_exe ONENOTE.EXE") {
WinActivate
}
RETURN
#IfWinActive ahk_class XLMAIN
$XButton2::
send {F2}
return
#IfWinActive
Your issue is that you're triggering the F2 hotkey by sending F2.
To avoid this, you'll want to use the $ modifier on your F2 hotkey like so:
$F2::
Seems like you actually have it on your XButton2 hotkey? Maybe you were on the right track but have it on the wrong hotkey? Either way, it isn't doing anything for you, so you can remove it.
(Alternative #UseHook can be specified somewhere above, so the keyboard hook is implemented for every hotkey after it)
And now a few miscellaneous fixes about your script. In AHK simple remaps are actually done like this:
XButton2::F2
Sweet clean little one-liner. (One-liner hotkeys don't need a return under them either)
So here would be your finished product:
$F2::
IF WinExist("ahk_exe ONENOTE.EXE") {
WinActivate
}
RETURN
#IfWinActive ahk_class XLMAIN
XButton2::F2
#IfWinActive
Personally I'd also omit the brackets, since they're not required for single line if-statements. But that's just preference of course. And also not sure why you've capitalized return.

How do I delete the current line using AutoHotkey?

Using an AutoHotkey script I'd like to set the keyboard command Ctrl+D to delete the current line in any active Windows app.
How?
^d::Send {Home}{ShiftDown}{End}{Right}{ShiftUp}{Del}
Might not work in all edge cases, but passes some very basic testing in Notepad. =~)
HaveSpacesuit's answer works but after using it for a while I realized it deletes the active line and sometimes re-positions the spacing of the line below.
This led me to rethink his solution. Instead of going from the front of the line to the back, I tried going from back to front. This solved the re-positioning issue.
SendInput {End}
SendInput +{Home}
SendInput ^+{Left}
SendInput {Delete}
There is still a small problem though. If the cursor is on an empty line, with more empty lines above, then all empty lines get deleted.
I don't know a key combo to replace ^+{Left} that doesn't have this behavior so I had to write a more comprehensive solution.
^d:: DeleteCurrentLine()
DeleteCurrentLine() {
SendInput {End}
SendInput +{Home}
If get_SelectedText() = "" {
; On an empty line.
SendInput {Delete}
} Else {
SendInput ^+{Left}
SendInput {Delete}
}
}
get_SelectedText() {
; See if selection can be captured without using the clipboard.
WinActive("A")
ControlGetFocus ctrl
ControlGet selectedText, Selected,, %ctrl%
;If not, use the clipboard as a fallback.
If (selectedText = "") {
originalClipboard := ClipboardAll ; Store current clipboard.
Clipboard := ""
SendInput ^c
ClipWait .2
selectedText := ClipBoard
ClipBoard := originalClipboard
}
Return selectedText
}
As far as I can tell this produces no unexpected behaviour.
However, be careful if you're using a clipboard manager as this script uses the clipboard, if necessary, as an intermediary to get the selected text. This will impact clipboard manager history.
In case you run into problems where you need different behaviours for different programs, you can "duplicate" your ^d command for specific programs like this:
SetTitleMatchMode, 2 ; Makes the #IfWinActive name searching flexible
^d::Send {Home}{ShiftDown}{End}{Right}{ShiftUp}{Del} ; Generic response to ^d.
#IfWinActive, Gmail ; Gmail specific response
^d::Send {Home}{ShiftDown}{End}{Right}{ShiftUp}{Del} ; adapt this line for gmail
#IfWinActive ; End of Gmail's specific response to ^d
#IfWinActive, Excel ; Excel specific response.
^d::Send {Home}{ShiftDown}{End}{Right}{ShiftUp}{Del} ; adapt this line for Excel
#IfWinActive ; End of Excel's specific response to ^d
This way your ^d command will work differently in Excel and Gmail.
I have a simple way to solve the repositioning issue. Without using the clipboard.
The repositioning issue is due to the need to handle 2 separate cases.
if there's existing text in a line,
we want to select them all, and delete the text (backspace 1)
and backspace one more time to delete the empty line (backspace 2)
if it's a blank line,
we want to delete the empty line (backspace 1)
To cater for both of above cases, I introduced a dummy character.
This will make sure BOTH cases will act the same way.
So doing backspace 2 times, will result in the same transformation each time.
Simply,
; enable delete line shortcut
^d::
Send {Home}
Send {Shift Down}{End}{Shift Up}
Send d
Send {Backspace 2}
Send {down}
return
Disadvantage with this approach,
the dummy character "d" will appear when you undo. Not a bad tradeoff since I don't undo delete lines very often.

Toggle keys in autohotkey

My goal is mapping WASD to the 4 arrow buttons on the keyboard and make 1 'Suspend' the script while z exits it. That was easy enough. Now I'd like a and d only apply conditionally. I look at the docs and I have no idea what's wrong here. I think I'm either using the if statement wrong or Left/Right doesn't work in if statements in which case I have no idea what to do.
#SingleInstance
a::if(UseAD) Left
d::if(UseAD) Right
1::Suspend
2::UseAD:=!UseAD
w::Up
s::Down
z::ExitApp
Try this:
#SingleInstance
$a::Send % UseAD ? "{Left}" : "a"
$d::Send % UseAD ? "{Right}" : "d"
1::Suspend
2::UseAD:=!UseAD
w::Up
s::Down
z::ExitApp
Okay now a break down.
Your If statement wasn't being evaluated correctly. The following line of code after the condition is met is what is run. Like so:
If (true)
do this
Your Hotkey is also wrong for a Multi lined statement. Essentially a single lined Hotkey is a basically a Send command for whatever key or keys specified on that line (unless you specify an assignment/function/command etc...) it will act as a Send Command does. To have an If evaluation requires multiple lines. When you specify a hotkey and you want an evaluation that will require multiple lines you, and must return from a Multi-Lined Hotkey same a Sub Routine:
a::
Code goes here
more code
etc..
Return
b::AnotherHotkey
etc..
Okay so lets plug this Logic in with your code:
#SingleInstance
a::
if(UseAD)
Left
return
d::
if(UseAD)
Right
return
1::Suspend
2::UseAD:=!UseAD
w::Up
s::Down
z::ExitApp
If you run this you'll get an Error about the Text Left... that is because instead of our Hotkey acting as Send command it's acting as a Sub Routine so we have to specify Send command with Left:
a::
if(UseAD)
Send, Left
return
But this isn't correct either, now it's sending the word Left instead of the Key left.. so again we have add Brackets around our named key like so:
a::
if(UseAD)
Send, {Left}
return
Okay, now a and b are not being sent when UseAD is False, so we must Send them by specifying with Else like so:
a::
if(UseAD)
Send, {Left}
else
Send, a
return
Now we run this code and press a or b get an Max Hotkeys reached message because our code is triggering the Hotkey in an Infinate loop. We need to specify our code in such a way that it will not trigger itself, like so:
$a::
if(UseAD)
Send, {Left}
else
Send, a
return
If you notice we have added a $ symbol in front of our hotkey, this adds a keyboard Hook to that Hotkey and will prevent the the script from triggering that hotkey itself. This is now a complete working script but looks entirely different from the first code I posted. That is because I like typing less lines, if I can.
In the first code sample I'm using a Forced Expression % on the Send command and Ternary ? : to evaluate UseAD and if true send Left key if false send the letter, exactly the same as above code, just more concise.

AutoHotKey code to receive ctrl+x while pressing ctrl+c twice

AutoHotKey code to receive CTRL+X while pressing CTRL+V twice
Can anyone help with this?
Many thanks!
Assuming we are talking about Ctrl+C, not V, and assuming you want to keep the original Ctrl+C function but also use it for Ctrl+X when pressing twice in a short time:
#persistent
Transform, cC, Chr, 3 ; store the value of ctrlC into cC.
hotkey, $^c, ctrlC, ON ; this is basically the same as if to say $^c::..., but only deactivable
return
ctrlC:
hotkey, $^c, ctrlC, OFF
input, key, M L1 T0.2
hotkey, $^c, ctrlC, ON
if errorlevel = timeout
send ^c
else if key = %cC%
send ^x
else
send %key%
return
should do..
also see Input for further information. I used this little hotkey-command-trick in order to temporarily disable the Ctrl+C-Hotkey, because otherwise input would not recognize the second c
In this example, I set timeout to 0.2 seconds. Change it to your convenience.
About your capslock idea - sounds like a good idea to me, but anyways, we're not a code-provider network. The command getKeyState should help you started.

Autohotkey setting up "..println" read something

I am trying to make shortcut using autohotkey where typing "println" produces "System.out.println();" but typing ".println" produces ".println();".
The purpose of this is to help me with something I commonly type when I'm writing code for my java course. I want use the regular keyboard dot to be not the numpad dot for this shortcut but I do not care about which dot is used in the output.
I have tried the following:
;for Java println
::println::
SendInput System.out.println();{Left}{Left}
return
;block change if '.println'
::.println::
SendInput {NumpadDot}println();{Left}{Left}
return
However, this only does the first shortcut and not the second.
Can you help me get this script to work?
Declare ::.println:: before ::println:: and your idea will work.
::. println:: ; you might wan't to add this in case you add a space after a ,
SendInput {NumpadDot}println();{Left}{Left}
return
::.println::
SendInput {NumpadDot}println();{Left}{Left}
return
::println::
SendInput System.out.println();{Left}{Left}
return