How to use HotString with variable & wildcard? - autohotkey

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
....

Related

Remap alphabetic keys to numeric when NumLock is On with AutoHotKey

I have a laptop DELL XPS 13 9310 that doesn't come with physical or togglable numeric keys and visible NumLock key. However, I have just discovered that I can press Fn+B to toggle the NumLock state as can be seen on a virtual keyboard.
Can AHK detect the NumLock state and rewrite M JKL UIO to 0 123 456?
And how do I write this detection mechanism?
I woul'd try something like:
#Persistent
#if GetKeyState("NumLock", "T")
ToolTip % GetKeyState("NumLock", "T")
M::
Send, 0
return
J::
Send, 1
return
K::
Send, 2
return
L::
Send, 3
return
U::
Send, 4
return
I::
Send, 5
return
O::
Send, 6
return
This is a bit grost, but, probably will do the job

Hold modifier keys

1. Briefly
I don't understand, how I can make these actions:
hold modifier keys,
print some symbols, when modifier keys hold,
drop modifier keys.
I need it, because I use Clipjump.
2. Expected behavior
Simply example:
Ctrl Down → V → V → Ctrl Up.
3. Actual behavior
Part of my script:
#t::
Send, {LCtrl Down}
Sleep, 1000
Send, {V}
Sleep, 1000
Send, {V}
Sleep, 1000
Send, {LCtrl Up}
return
Ctrl Down → V → Ctrl Up, Ctrl Down → V → Ctrl Up.
4. Did not help
In Google, I write queries, for example, autohotkey hold modifier keys, autohotkey hold ctrl, but I can get no answer to my question.
You might try the different send modes. SendInput for example. You might use a plain "v" (instead of a shifted - capital - "V"). You might add a key multiplier {key #} instead of repeating.
#t::
SendInput, {LCtrl Down}
Sleep, 1000
SendInput, v
Sleep, 1000
SendInput, v
Sleep, 1000
SendInput, {LCtrl Up}
return
Or Better yet:
#t::
SendInput, {LCtrl Down}
Sleep, 1000
SendInput, {v 2}
Sleep, 1000
SendInput, {LCtrl Up}
return
or even:
#t::
SendInput, {LCtrl Down}{v 2}{LCtrl Up}
return
EDITed per comment: You might also try just using the ordinary ahk facility with modifiers, and try it under the different send modes, too:
#t::
Send, ^{v 2}
return
Hth,

Wait for previous process to finish before starting new one

I need to find a way in AHK to wait for a program to finish, before starting a new one.
Basically, I have a script that opens an application and inputs some parameters. The application then spends an unknown amount of time processing the input data.
Unfortunately, at the moment the ahk script ends before the application has finished processing, at which point the same ahk script is run again and does not work / interrupts the previous processing.
edit: (the ahk .exe is called using subprocess calls in Python)
is there a way or any methods to help with this?
For reference, the script:
#NoEnv
CoordMode, Mouse, Window
SendInput Mode Input
#SingleInstance Force
SetTitleMatchMode 2
#WinActivateForce
SetControlDelay 1
SetWinDelay 0
SetKeyDelay -1
SetMouseDelay -1
SetBatchLines -1
if 0 < 2 ; The left side of a non-expression if-statement is always the name of a variable.
{
MsgBox, This script requires 2 incoming parameters but it only received %0%.
ExitApp
}
IfWinNotExist, ahk_exe photoscan.exe
{
Run, "C:\Program Files\Agisoft\PhotoScan Pro\photoscan.exe"
}
sleep, 200
WinActivate, ahk_exe photoscan.exe
sleep,5
WinMaximize, ahk_exe photoscan.exe
;Macro5:
Click, 476, 438, 0
SendInput {LControl Down}
SendInput {r}
Click, -56, 157, 0
WinActivate, Run Python Script ahk_class QWidget
sleep, 400
SendInput {LControl Up}
SendInput {LControl Down}
SendInput {a}
SendInput {LControl Up}
sleep, 400
SendInput {Backspace}
SendInput %1% ; 1st argument is the photoScan API scriptimages folder directory
SendInput {Tab}
SendInput {Tab}
sleep, 400
SendInput {LControl Down}
SendInput {a} ; 2nd argument is additional args (in our case, the projectName)
SendInput {LControl Up}
SendInput {Backspace}
SendInput %2% ; 2nd argument is the images folder directory & name of output log, model and texture
Sleep, 703
SendInput {Enter}
Click, 476, 438, 0
Return
You have:
IfWinNotExist, ahk_exe photoscan.exe
{
Run, "C:\Program Files\Agisoft\PhotoScan Pro\photoscan.exe"
}
sleep, 200
Which is set to start/launch the application if it is not running. Then a sleep to allow two tenths of a second for it to load (which is probably too small).
Instead of just a ‘sleep’ you have to ‘WinWait’ or ‘WinWaitActive’, found at this link:
https://autohotkey.com/docs/commands/WinWaitActive.htm
Like this sample:
Run, "C:\Program Files\Agisoft\PhotoScan Pro\photoscan.exe"
WinWaitActive, ahk_exe photoscan.exe, , 2
if ErrorLevel
{
MsgBox, WinWait timed out.
return
}
else
WinMinimize ; minimize the window found by WinWaitActive.
You may also have to use the window inspector to get the true name of the window/application/process name.

Unintended characters being sent to output

Below script :
:*:mw::
Send, {Ctrl Down}{RWin Down}{x Down}{Ctrl Up}{RWin Up}{x Up}
sends characters "cp" to screen once it runs.
So if I am in a text editor and type "mw" then "cp" is sent to the editor.
How can amend the script so that it just fires the keys "Ctrl,WindowsKey,x" ?
You need a return:
:*:mw::
Send, {Ctrl Down}{RWin Down}{x Down}{Ctrl Up}{RWin Up}{x Up}
return ; Add this to return without continuing to execute statements after this line
Send, cp ; Just a guess, I think you have this line somewhere here
You can omit return if Send is at the same line as the hotkey:
:*:mw::Send, {Ctrl Down}{RWin Down}{x Down}{Ctrl Up}{RWin Up}{x Up}

Shift Key Training Wheels and Shift Parenthesis Remap

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