how to switch LAlt and LShift using AutoHotKey - autohotkey

I need RAlt + LAlt + g to behave as LShift + Del (nothing happend)
#InputLevel, 1
RAlt::F24
#inputLevel, 0
F24 & g::Del
LAlt::LShift
I test RAlt + RShift + g it works fine,
also I test to change the key g to d and it works too!!
#InputLevel, 1
RAlt::F24
#inputLevel, 0
F24 & d::Del
LAlt::LShift
did I miss something !?

Related

Preventing physical key presses from conflicting with sent keys using AutoHotKey

I want to define a shortcut using autohotkey that automates navigation to the Cell Width text box in Word's ribbon menu (i.e. sends the keys Alt,j,l,w while in Word).
My initial attempt at a script introduces an issue where the Up actions of the physical key presses haven't completed before the keys are sent by the script, causing it to fail.
Although I have a workaround (using sleep 250, shown further below), I would like to understand whether there is a more elegant solution - e.g. this value was chosen by trial and error, and this workaround may fail on a different machine, or if my laptop is having a bad day.
Essentially, I would like to find a solution that avoids hardcoding a wait duration.
Any suggestions?
The issue
In my initial script I tried to define the hotkey Alt+Shift+p in Word, to send Alt,j,l,w in sequence. This fails and enters the text "jlw" into the active table cell instead.
This is because for keys physically pressed (marked with # in comments below), the Up actions are yet to run when the script has already begun sending keys (indicated with $). This disrupts the send sequence Alt,j,l,w so it fails.
Also note events marked with ? may be a byproduct of the failed actions.
Script
; Jump to table cell width entry when Alt+Shift+p pressed in Word only
#IfWinActive, ahk_exe WINWORD.EXE
!+p::
Send, {RAlt down}{RAlt up}jlw
Return
Key history
VK SC Type Up/Dn Elapsed Key Comment
-------------------------------------------------------------------------------------------------------------
A4 038 d 1.03 LAlt #
A0 02A d 0.14 LShift #
50 019 h d 0.13 p #, h=Hook Hotkey
A5 138 i d 0.02 RAlt $
A5 138 i u 0.00 RAlt $
11 01D i d 0.00 Control ?
11 01D i u 0.00 Control ?
A4 038 i u 0.00 LAlt #
A0 02A i u 0.00 LShift #
4A 024 i d 0.00 j $
4A 024 i u 0.00 j $
4C 026 i d 0.00 l $
4C 026 i u 0.00 l $
57 011 i d 0.00 w $
57 011 i u 0.00 w $
11 01D i d 0.00 Control ?
A4 038 i d 0.00 LAlt ?
11 01D i u 0.00 Control ?
A0 02A i d 0.00 LShift ?
50 019 s u 0.08 p #
A0 02A u 0.25 LShift ?
A4 038 u 0.00 LAlt ?
Workaround
By adding a sleep 250 statement, the hotkey and sent keys run in the intended sequence. Note no other keys are triggered (nothing indicated with ?).
Script
; Jump to table cell width entry when Alt+Shift+p pressed in Word only
#IfWinActive, ahk_exe WINWORD.EXE
!+p::
Sleep 250
Send, {RAlt down}{RAlt up}jlw
Return
Key history
VK SC Type Up/Dn Elapsed Key Comment
-------------------------------------------------------------------------------------------------------------
A4 038 d 0.39 LAlt #
A0 02A d 0.20 LShift #
50 019 h d 0.20 p #, h=Hook Hotkey
50 019 s u 0.11 p #
A0 02A u 0.11 LShift #
A4 038 u 0.00 LAlt #
A5 138 i d 0.03 RAlt $
A5 138 i u 0.00 RAlt $
4A 024 i d 0.00 j $
4A 024 i u 0.00 j $
4C 026 i d 0.00 l $
4C 026 i u 0.00 l $
57 011 i d 0.00 w $
57 011 i u 0.00 w $, SUCCESS!
If the target window does not receive the keystrokes reliably, you can try increasing the press duration in the send command via the second parameter of SetKeyDelay, eg.
!+p::
SetKeyDelay, 10, 10
Send, {RAlt down}{RAlt up}jlw
Return
Not sure why you're using right alt, don't think that's supposed to work even. Just use "Alt". And I think your hotkey is not very good for this. Word gets confused with the input.
But I think maybe doing this, could work
!+p up:: ;up means it'll run once u release p, might help a bit
SetKeyDelay, 500, 10 ;good amount of delay, can probably do with less
Send, {Shift Up}{Alt Up}{Alt}jlw ;send shift and alt up first
Return
And now for a better alternative option, automating it with the Word ComObject. Usage of VBA for this is the normal and intended way, but you can AHK (or any other language) just as well.
Here's a quick AHK example of changing the first table's first cell's width:
Word := ComObjActive("Word.Application")
Word.ActiveDocument.Tables(1).Cell(1, 1).Width := 500
Of course that's not a very good way to go about this, I'm sure you can reference the active table and active cell somehow, I just quickly read the docs and wrote that. Haven't actually ever used any of this stuff in practice myself.
I found a more elegant solution using KeyWait. Compared to my earlier workaround script, I consider this more elegant since it doesn't require hardcoding a wait duration. This simply waits for the pressed keys to come up before the script continues, preventing any conflict:
Script
#IfWinActive, ahk_exe WINWORD.EXE
!+p::
KeyWait Alt
KeyWait Shift
KeyWait p
Send, {Alt Down}{Alt Up}jlw
Return
Key history
VK SC Type Up/Dn Elapsed Key Comment using previous notation
-------------------------------------------------------------------------------------------------------------
A4 038 d 0.63 LAlt #
A0 02A d 0.11 LShift #
50 019 h d 0.11 p #
50 019 s u 0.06 p #
A0 02A u 0.19 LShift #
A4 038 u 0.00 LAlt #
12 038 i d 0.01 Alt $
12 038 i u 0.00 Alt $
4A 024 i d 0.00 j $
4A 024 i u 0.00 j $
4C 026 i d 0.00 l $
4C 026 i u 0.00 l $
57 011 i d 0.00 w $
57 011 i u 0.00 w $
Interestingly, the above script modified to use Send, !jlw works (i.e. navigates to the Cell Width box) but the sent keys come Up out of sequence as follows. I won't use this, just to avoid any unintended consequences of this occurring out of sequence.
VK SC Type Up/Dn Elapsed Key Comment
-------------------------------------------------------------------------------------------------------------
A4 038 d 1.17 LAlt
A0 02A d 0.11 LShift
50 019 h d 0.14 p
50 019 s u 0.09 p
A0 02A u 0.16 LShift
A4 038 u 0.00 LAlt
A4 038 i d 0.02 LAlt <--
4A 024 i d 0.00 j
4A 024 i u 0.00 j
A4 038 i u 0.00 LAlt <--
4C 026 i d 0.00 l
4C 026 i u 0.00 l
57 011 i d 0.00 w
57 011 i u 0.00 w

Why isn't my ImageSearch command working?

I am writing a script which uses the ImageSearch command.
The script starts by pressing F3 and it scans from 900,55 to 1005,72.
If it locates any of these 3 identical images, it should send F1, otherwise it should keep scanning until I press F12.
I tried changing the resolution and such but to no success.
F3::
SendMode , Input
SetMouseDelay , -1
SetBatchLines , -1
Loop
{
ImageSearch ,,, 0 , 0 , A_ScreenWidth , A_ScreenHeight , para1.png
bT := ErrorLevel ? bT : 1
ImageSearch ,,, 0 , 0 , A_ScreenWidth , A_ScreenHeight , para2.bmp
bT := ErrorLevel ? bT : 1
ImageSearch ,,, 0 , 0 , A_ScreenWidth , A_ScreenHeight , para3.png
bT := ErrorLevel ? bT : 1
If bT
{
bT := 0
Send , {F1}
Sleep , 100
}
}
Return
f12::ExitApp
thanks for the correction #GoldenLizard

AutoHotKey does not recognize AltGr+Alt+Y

Most of the keys work in combination with AltGr+Alt+[key]. The not working exceptions I found are y and . (period). I am following this instruction (https://www.autohotkey.com/docs/KeyList.htm#SpecialKeys Step 1 to 5) in order to analyze the problem.
Log output for AltGr+Alt+x (my AHK script is working with that shortcut)
A2 01D d 11.34 LControl
A5 138 d 0.00 RAlt
A4 038 d 0.13 LAlt
58 02D d 0.20 x
58 02D u 0.13 x
A2 01D u 0.17 LControl
A5 138 u 0.00 RAlt
A4 038 u 0.00 LAlt
Log output for AltGr+Alt+y (my AHK script is NOT working with that short cut)
A2 01D d 1.89 LControl
A5 138 d 0.00 RAlt
A4 038 d 0.05 LAlt
A2 01D u 0.36 LControl
A5 138 u 0.00 RAlt
A4 038 u 0.06 LAlt
This log output leads me to believe, that the problem is not my script, but something more global. It seems that AHK is not even receiving the key stroke for "y".
Log output for AltGr+y to prove that my keyboard isn't defective :)
A2 01D d 10.27 LControl
A5 138 d 0.00 RAlt
59 02C d 0.23 y
59 02C u 0.13 y
A2 01D u 0.17 LControl
A5 138 u 0.00 RAlt
Can any of you reproduce this? How can I use AltGr+Alt+Y as a shortcut?
I am using Win10 x64 and AHK Version 1.1.30.01.
Edit
Obviously, the issue is only on my computer. So I would like to change the question slightly into: How can I identify and eliminate the reason that blocks some hotkeys? Remember that AltGr+Alt+Y is not the only hotkey that does not work, also AltGr+Alt+. and AltGr+Alt+O and possibly more that I have not tested yet.
Instead of AltGr+LAlt+Key or AltGr+RControl+Key which may cause issues in some programs or key jamming, you can use any other key in place of LAlt or RControl this way:
LControl & RAlt:: AltGr := true ; assign the boolean value "true" to the variable 'AltGr''
LControl & RAlt Up:: AltGr := false
; The #If directive creates context-sensitive hotkeys and hotstrings
#If (AltGr) ; If this variable has the value "true"
a:: MsgBox AltGr+a
a & b:: MsgBox AltGr+a+b
b & a:: MsgBox AltGr+b+a
h & l:: Send Hello
i & e:: Run iexplore.exe
n & p:: Run notepad
w & p:: Run wordpad
#If ; turn off context sensitivity
https://autohotkey.com/docs/commands/_If.htm

How to maintain proper column spaces while printing rows of a text file in perl

I am trying to edit few lines of my file and create new file with all modifications
My lines are not in paragraph format, it looks something like this below,
R1 X XA 0i 1i H 0i
R2 X XA 1i 1i H 0i
R3 X XA 1i 1i H 0i
R4 X XA 1i 1i H 0i
R5 X XA 1i 1i H 0i
R6 X XA 0i 0i X 0i
They clearly don't have equal spacing between each item in row, but they are aligned column basis.
I wand to edit R3 3rd item from XA to XAHBB
but unable to maintain the column alignment
my $cur_line_num = 1;
while(<Sourcefile>){
my #RowEdit = split (" ",$_);
if($RowEdit[0]=~ m/^R3$/s){
$RowEdit[2]="RowEdit[2]HBB"
}
my $curr_line = join(" ", #RowEdit)
print $newfile "curr_line\n";
$cur_line_num++;
}
print "$cur_line_num\n";
My current output is as shown below
R1 X XA 0i 1i H 0i
R2 X XA 1i 1i H 0i
R3 X XAHBB 1i 1i H 0i
R4 X XA 1i 1i H 0i
R5 X XA 1i 1i H 0i
R6 X XA 0i 0i X 0i
Where as my expected output should look something like this below
R1 X XA 0i 1i H 0i
R2 X XA 1i 1i H 0i
R3 X XAHBB 1i 1i H 0i
R4 X XA 1i 1i H 0i
R5 X XA 1i 1i H 0i
R6 X XA 0i 0i X 0i
How to maintain column alignment while editing a file?
That's what Text::Table is for:
#!/usr/bin/perl
use warnings;
use strict;
use Text::Table;
my $table = 'Text::Table'->new;
while (<DATA>) {
my #RowEdit = split ' ';
if ($RowEdit[0] eq 'R3') {
$RowEdit[2] .= 'HBB';
}
$table->add(#RowEdit);
}
print $table;
print $. + 1, "\n";
__DATA__
R1 X XA 0i 1i H 0i
R2 X XA 1i 1i H 0i
R3 X XA 1i 1i H 0i
R4 X XA 1i 1i H 0i
R5 X XA 1i 1i H 0i
R6 X XA 0i 0i X 0i
Also note all the other small changes I made:
No need to use a new variable to count lines. Perl already has $..
/s changes the behaviour of . in a regex. It makes no sense to use it in a regex that doesn't contain a dot. Moreover, eq can be used for string equiality if there's only one string that matches the regex - it's easier to read and faster to run.
split uses $_ as the second argument if none is provided. Typing $_ anywhere outside grep or map is a code smell - either it's something worth a name, or could be written without it.
To append a string, you can use the .= operator.
You can do this with printf(). But you need to make two passes over the data (as there's no way to know what the widest column width are until you have seen every data record).
Something like this seems to do the trick.
#!/usr/bin/perl
use strict;
use warnings;
my #widths; # Store the max widths for each column
my #data; # Store the actual data
while (<DATA>) {
my #row;
# Use the first line to initialise the #widths array
if ($. == 1) {
#row = /(\S+\s*)/g;
#widths = map { length() - 1} #row; # Subtract 1 for gutter
#row = map { s/\s+$//; $_ } #row; # Remove trailing whitespace
} else {
#row = split;
}
# Split the data
my #row = split;
# Store the split data
push #data, \#row;
# Make the (optional) transformation
$row[2] .= 'HBB' if $row[0] eq 'R3';
# Look at each column in this row of data and
# compare it to the widest data that we've previously
# seen in that column.
for my $i (0 .. $#row) {
$widths[$i] = length $row[$i]
if length $row[$i] > ($widths[$i] // 0);
}
}
# Create a printf output format using the column
# widths we've stored in #widths
my $fmt = join ' ', map { "%-${_}s" } #widths;
# Use printf to display each line of data.
printf "$fmt\n", #$_ for #data;
__DATA__
R1 X XA 0i 1i H 0i
R2 X XA 1i 1i H 0i
R3 X XA 1i 1i H 0i
R4 X XA 1i 1i H 0i
R5 X XA 1i 1i H 0i
R6 X XA 0i 0i X 0i
The output is:
R1 X XA 0i 1i H 0i
R2 X XA 1i 1i H 0i
R3 X XAHBB 1i 1i H 0i
R4 X XA 1i 1i H 0i
R5 X XA 1i 1i H 0i
R6 X XA 0i 0i X 0i
But I think the Text::Table solution is better :-)
As this is one of the tasks Perl was originally written for (Practical Extraction and Reporting Language), then for completeness also good ol' plain Perl formats should be mentioned, see man perlform. E.g.
format STDOUT =
#<<<<< # #<<<<, ....
$col1, $col2, $col3, ...
.
for my ... (...) {
# set $col1 .... and then
write
}

AutoHotKey: #IfWinActive not working

So I was making a AFK stopper with AHK but I need it to only run in one program so I used #If WinActive but to no avail.
#If WinActive("ahk_class WINDOWSCLIENT")
while( 1 = 1 ) {
Send, {W down}
sleep 240
Send, {W up}
sleep 240
Send, {A down}
sleep 240
Send, {A up}
sleep 240
Send, {S down}
sleep 240
Send, {S up}
sleep 240
Send, {D down}
sleep 240
Send, {D up}
}
The #IfWin directives are only for creating context-sensitive hotkeys and hotstrings.
Try using a loop or SetTimer with IfWinActive:
Loop
{
If WinActive("ahk_class WINDOWSCLIENT")
{
while( 1 = 1 )
{
; do something
}
}
}