is it possible (how?) to change the Hotstring and the Endchars with another Hotkey?
A:
#Hotstring EndChars `n `t
#Hotstring o
;#Hotstring *
B
;#Hotstring EndChars `n `t
;#Hotstring o
#Hotstring *
I want to switch between direct input (B) and input after an Endchar (A).
Directives cannot be executed conditionally. The only solution I can see is to use an included script that you can change the content this way:
F1::
FileAppend,
(
#Hotstring EndChars ``n ``t
#Hotstring o
), %A_ScriptDir%\Hotstring_Directives_tmp.ahk
Sleep, 300
FileMove, %A_ScriptDir%\Hotstring_Directives_tmp.ahk, %A_ScriptDir%\Hotstring_Directives.ahk, 1 ; overwrite
Sleep, 300
Reload
return
F2::
FileAppend,
(
#Hotstring *
), %A_ScriptDir%\Hotstring_Directives_tmp.ahk
Sleep, 300
FileMove, %A_ScriptDir%\Hotstring_Directives_tmp.ahk, %A_ScriptDir%\Hotstring_Directives.ahk, 1 ; overwrite
Sleep, 300
Reload
return
; ...
#Include %A_ScriptDir%\Hotstring_Directives.ahk
; your Hotstrings here
Note that you have to create the script Hotstring_Directives.ahk manually if it doesn't already exist.
Related
The AHK script below should use 7-zip to extract a folder when ctrl+ALT+Left is pressed. When you manually right-click on a folder and then type "7eee" and then press enter, the folder extracts. I'd like to mimic this without the right-click and instead use the keyboard shortcut. I tried to do this two ways:
;alt + ctrl
!^LButton::
blockinput on
send {LButton}{RButton}7eee{enter}
blockinput Off
return
I also tried:
;alt + ctrl
!^LButton::
temp = %clipboard%
KeyWait, LButton, D
send {LButton}
sleep,100
Send, {Ctrl Down}c{Ctrl Up}
file = %clipboard% ;get file address
clipboard = %temp% ;restore clipboard
outdir := getdir(file)
if (A_Is64bitOS = 1)
{
runwait, "C:\Program Files\7-Zip\7z.exe" x "%file%" -o"%outdir%" -y,,hide
}
else
{
runwait, "C:\Program Files (x86)\7-Zip\7z.exe" x "%file%" -o"%outdir%" -y,,hide
}
msgbox, 7zip has finished extracting "%file%".
return
getdir(input)
{
SplitPath, input,,parentdir,,filenoext
final = %parentdir%\%filenoext%
return final
}
EDIT:
I have found something that works:
#IfWinActive, AHK_EXE Explorer.exe
^e::
temp = %clipboard%
Send, {Ctrl Down}c{Ctrl Up}
file = %clipboard% ;get file address
clipboard = %temp% ;restore clipboard
outdir := getdir(file)
if (A_Is64bitOS = 1)
{
runwait, "C:\Program Files\7-Zip\7z.exe" x "%file%" -o"%outdir%" -y,,hide
}
else
{
runwait, "C:\Program Files (x86)\7-Zip\7z.exe" x "%file%" -o"%outdir%" -y,,hide
}
msgbox, 7zip has finished extracting "%file%".
return
getdir(input)
{
SplitPath, input,,parentdir,,filenoext
final = %parentdir%\%filenoext%
return final
}
#If
But I do not like the message box and I wish there were a progress bar or indication that it is in the process of extracting.
This is an old question and you're probably fine with the workaround you've found, but if you're still looking for a simple script that mimics the mouse/keyboard procedure, here it is:
^#!z:: ;// Ctrl + Alt + Win + Z
blockinput on
Sleep, 300
SendInput, {AppsKey}
Sleep, 100
SendInput, 7
Sleep, 100
SendInput, e
Sleep, 100
SendInput, e
Sleep, 100
SendInput, e
Sleep, 100
SendInput, {Enter}
blockinput on
Return
I did not try your code but in general, using the context menu key (AppKey) is more reliable than mouse button clicks, and also adding some sleep time between key strokes helps. If the script doesn't work, you may need to increase the sleep time intervals, 100 ms at a time, till it works.
In Onenote, let's say I want to write x^y (x to power of y), I would need to enter Equ mode (by keyboard shortcut) , type x^y , hit Space, then exit equ mode
So, I figure it could be something like this :
::(wild_card)^(wild_card)::
Send, (Shortcut for equ mode)
Send, variable1
Send, ^
Send, variable2
Send, space
Send, (Shortcut for equ mode)
How do I actually achieve this ?
Alternatively, the same purpose could be formulated by doing,
- monitor word separated by Ending chars
- detect if ^ is in those word
- Send (Shortcut) , then the word, then space, then (Shortcut).
Is this more doable ?
Thanks MCL,
Here is the code for auto convert x_y and x^y into their mathematical representation in onenote
#Include DynamicHotstrings.ahk
#IfWinActive, ahk_class Framework::CFrame
hotstrings("(\w+\_\w+) ","dowork")
hotstrings("(\w+\^\w+) ","dowork")
dowork:
Send, {LAlt Down}{=}{LAlt Up}
SendRaw, %$1%
Send, {Space}
Send, {LAlt Down}{=}{LAlt Up}
Send, {Space}
Return
Better yet , you can modify the DynamicHotstrings.ahk so it will ignore auto convert when we are already in equation mode:
hotstrings(k, a = "")
{
CoordMode,Pixel,Screen
PixelGetColor, color, 455, 1
if (color = 0xD7337F)
return
....
!c::
file_name = footnote.ini
restore_original_clipBoard := clipboard
clipboard =
KeyWait, Alt
KeyWait, c ;small c
BlockInput, on
SendEvent, ^{ins} ;^c doesn't work
ClipWait, 2 ; Wait for the clipboard to contain text.
if ErrorLevel
{
MsgBox Failed to save the selection: %clipboard%
exit
}
BlockInput, off
save_selection := clipboard
Problem: Despite a selection being made, Sendevent ^{ins} does not save it to the clipboard. Sometimes I have to repeat my hotkey, alt + c several times before the selection is being copied to the clipboard. The KeyWait should ensure me that only ^{ins} is being processed without any additional keys. What am I doing wrong here?
UPDATE
One of the ways I tried to force copy a selection to the clipboard was by using a while loop. I got it to work through the post: Looping clipboard and errorlevel evaluation not working as expected
PROBLEM
When I make a selection and press alt + c it sometimes gets stuck in the infinite loop that I implemented. But as you can see from that code:
clipboard := ""
while( StrLen(clipboard) < 1 )
{
Send, ^{ins}
Sleep, 50
}
MsgBox % ClipBoard
The infinite loop incorporates within itself a continues resending of ^{ins}. For some reason, my selection is not being recognized as a selection. Whilst it is in that infinite loop, I try to reselect the text. It then recognizes it instantly and copies my selection to the clipboard. But alas! The selection is incomplete because it goes so quick.
This problem is not always like that. Sometimes it recognizes the selection first spot on! So sometimes it copies my selection to my clipboard sometimes not. When it does not, then a resending of a ^{ins} does not seem to work. I do not want to the user to reselect his selection. Is that possible to do?
Send {Ctrl Down}{c}{Ctrl Up}
That presses Ctrl+C, you must do it instantly as one command apposed to pressing Ctrl waiting then pressing C.
Never seen Insert key used for copying text.
Also found this sends Ctrl+C as well.
Send, ^c
To send insert key use
{Insert}
This way works for me:
!vk43:: ; alt+c
clipContent:=ClipboardAll
Clipboard:=""
SendEvent, ^{Ins}
ClipWait, .75
MsgBox, % 262 . (ErrorLevel ? 160:208)
, % ErrorLevel ? "Period expired:":"Result:"
, % ErrorLevel ? "Failed to save the selection.":Clipboard
, % (ErrorLevel ? 0:2) . .5
Clipboard:=clipContent
KeyWait, vk43
Return
!vk43:: ; alt+c
clipContent:=ClipboardAll ; backup clipboard content (if needed)
Clipboard:="" ; no comment :)
Loop
{
SendEvent, ^{Ins}
ClipWait, .75 ; means 750ms, same if write 0.75
; assign value of "ErrorLevel" an variable for further usage
errLvl:=ErrorLevel
; monitoring current action (for debugging purpose only)
TrayTip, % "attempt: #"A_Index
, % """ErrorLevel"" of ""ClipWait"" command is: "errLvl
}
; here you can set the condition of ending the cycle: either...
; ...variable errLvl has not a true value,...
; ...or the number of attempts is equal 5
Until, Not errLvl Or A_Index=5
; value of each field of the command "MsgBox"...
; ...are set depending on the value of errLvl variable...
; ...using a ternary expression
; means if errLvl is a true, "options" field is 262160
MsgBox, % 262 . (errLvl ? 160:208)
; means that "title" has a couple variants
, % errLvl ? "Period expired:":"Result:"
; means that "text" has a couple variants
, % errLvl ? "Failed to save the selection.":Clipboard
; means if errLvl is a true, "timeout" field is 0.5 (500ms)
, % (errLvl ? 0:2) . .5
/* same that and above:
IfEqual, errLvl, % True, MsgBox, 262160
, % "Period expired:"
, % "Failed to save the selection."
, 0.5
Else MsgBox, 262208, % "Result:", % Clipboard, 2.5
*/
TrayTip ; remove "TrayTip" (for debugging purpose only)
; save an positive result (if needed)
IfEqual, errLvl, 0, Sleep, -1, someVar:=Clipboard
; return a temporarily saved data into clipboard (if needed)
Clipboard:=clipContent
KeyWait, % "vk43"
Return
From my experience whenever keystrokes are not recognized reliably it's due to either the system or the targeted program not keeping up with the speed at which those keys are sent.
For SendEvent you could try something like SetKeyDelay, 1000, 1000 and see if this improves things. The other option would be to send explicit down and up keys with intermittent sleep calls as outlined in this answer.
I'm looking to use AutoHotKey to modify the functionality of my shift keys. The functionality is described in Steve Losh's Blog entry here. Specifically, I'd like my shift keys to do the following:
If LShift or RShift is pressed and released in under 300 ms with no other keys being pressed in between, send ( or ), respectively.
If LShift and RShift are "rolled" together (press LShift, press RShift, release LShift, release RShift, etc.) in under 300ms, send () or )(.
If a shift key is used improperly (LShift and S, RShift and K, etc.) then nothing happens.
I've been having issues with the 300ms requirement and the "rolling" functionality. Specifically, I'm having issues with only being able to detect when the key is released due to the hotkey combos such as:
LShift & 0:: return
This is where I'm at so far:
LShift::
Send {LShift Down}
KeyWait, LShift
Send {LShift Up}
if (A_TimeSinceThisHotkey < 300){
if (A_PriorKey = "LShift")
{
Send {)}
}
}
return
I don't see a reason to use a 300 ms timeout anyway, it seems unreliable and unnecessary.
Have a look at this commented code, it is short and efficient, and seems to meet all of your requirements:
LShift::Send, (
RShift::Send, )
LShift & RShift:: Send, ()
RShift & LShift:: Send, )(
/* Put your unwanted combinations here
* and let them do nothing
*/
LShift & q::return
RShift & y::return
Edit:
Since LShift and RShift already are prefix hotkeys, I left out the trick described here.
MCL's answer is close but when I tested it I found that shift-clicking didn't select text. Here's a version with a passthrough to allow shift-clicking to work.
;shift to parens
LShift::Send, (
RShift::Send, )
LShift & RShift:: Send, ()
RShift & LShift:: Send, )(
;passthrough for shift-click
LShift & LButton::
Send, {LShift Down}{LButton}
Send, {LShift Up}
RShift & LButton::
Send, {RShift Down}{LButton}
Send, {RShift Up}
I don't think the 300ms timeout is possible without either very deep understanding of autohotkey's implementation or actual modification to autohotkey. When I tried to get it to work (using http://www.autohotkey.com/board/topic/98742-remapping-shift-key/) I found that A_PriorHotkey was not consistently populated. I don't think that variable was meant to work with modifier keys this way.
I felt compelled to figure this one out. Here you go!
I basically created a hotkey for every Shift + Letter key combination in order to send the correct key case and also set the Abort value. The Abort value is then referenced whenever one of the Shift keys is pressed in order to determine whether or not to send the corresponding ( or ).
The "Rolling" was accomplished by creating a Hotkey for LShift + RShift (and the opposite). It then looks to see which key is released first to determine () or )(.
Accept if this was what you were looking for!
Loop 26
{
Hotkey, % "~LShift & " Chr(A_Index+96), LetterKey ; Hotkeys for A-Z
Hotkey, % "~RShift & " Chr(A_Index+96), LetterKey ; Hotkeys for A-Z
}
Return
RShift::
LShift::
Abort := 0
keyDown := A_TickCount
Keywait, % A_ThisHotkey
duration := A_TickCount - keyDown
If (duration < 200) and (Abort = 0)
SendInput % (A_ThisHotkey = "LShift") ? "(" : ")"
Send {LShift Up}
Return
RShift & LShift::
LShift & RShift::
Keywait, LShift
If GetKeyState("RShift", "P")
{
Keywait, RShift
Send ()
}
Else
Send )(
Return
LetterKey:
SendInput, % "+" SubStr(A_ThisHotKey, 0, 1)
Abort := 1
Return
EDIT:
Hmm, I seem to be having the same problem as you. I always get a duration of 0 due to the hotkeys.
I found and modified this script on the AutoHotKey Forums. (The original script was prone to type "K(" when you meant to type "K" if you type too quickly, so I've modified it so that shouldn't happen any more)
$LShift Up::send, % getkeystate("LShift") ? "{LShift Up}" : ""
$RShift Up::send, % getkeystate("RShift") ? "{RShift Up}" : ""
~$LShift::
KeyWait, LShift, T0.1 ; wait 100ms to check shift state
if (A_PriorKey = "LShift")
{
send, % getkeystate("LShift") ? "{LShift Down}" : "("
}
KeyWait, LShift
return
~$RShift::
KeyWait, RShift, T0.1 ; wait 100ms to check shift state
if (A_PriorKey = "RShift")
{
send, % getkeystate("RShift") ? "{RShift Down}" : ")"
}
KeyWait, RShift
return
I have this simply script in Autohotkey:
:*:teams::
(
milan
juventus
inter
roma
lazio
napoli
mantova
)
When i type teams on Notepad my output is the list of teams (milan, juventus..)
if i use a physical keyboard to type teams this script work for me
, but if use a virtual keyboard to type teams i have no list on Notepad:
and if i run the script to type teams automatically
WinWait, *new 2 - Notepad++,
IfWinNotActive, *new 2 - Notepad++, , WinActivate, *new 2 - Notepad++,
WinWaitActive, *new 2 - Notepad++,
MouseClick, left, 133, 117
Sleep, 100
Send, squadre
the script doesn't replace teams with the list of teams
Why the script works only if i type with a physical keyboard?
is there a solution to replace words, sentences with my scripts without using physical keyboard?
Sorry if i am noob
You can use the Input command.
loop {
While !RegexMatch(strCapture, "teams$") {
Input, strUserInput, V L1, {BackSpace} ; V: visible, L1: Character length 1
If ErrorLevel = Endkey:BackSpace
strCapture := SubStr(strCapture, 1, StrLen(strUserInput) - 1)
else
strCapture .= strUserInput
; tooltip % ErrorLevel "`n" strUserInput "`n" strCapture "`n" ; enable this to see what actually happens
}
SendInput,
(Ltrim
{Backspace 5}
milan
juventus
inter
roma
lazio
napoli
mantova
)
strCapture := ""
}