AHK shortcuts for Alt+Space in Windows - autohotkey

running AHK in Windows 10, and I'm trying to create shortcuts for the Alt+Space menu. Specifically, I often use this sequence:
Press keys Alt+Space (bring up the window menu)
Press key S (select Size to resize)
Press key Left (now moving the mouse is resizing your window horizontally)
Press key Up (now moving the mouse is resizing your window in all directions)
Once this sequence is pressed, you can move your mouse to resize the active window as if you click-dragged the top-right corner, without having to hunt for that corner. (to finalize the resizing you can press Enter of LeftMouseKey, or Esc to abort). I'd like to get to this state with a single shortcut.
Here is my current script, binding to Winkey+Ctrl+Shift+1
;resize window from Top-Left
#^+1::
SendInput !{Space}
Sleep 100
SendInput s
Sleep 100
SendInput {Left}+{Up}
Return
It works mostly, but sometimes the active window will consume the s {Left} {Up} commands, rather than the popup menu. Thus, sometimes this shortcut will result in the active window like VSCode having the "s" character and the cursor 1 line up from before (as if typing s {Left} {Up}), and a visible Alt+Space menu.
I initially used Sleep 10 and thought Sleep 100 would fix this, but it didn't. The shortcut already feels slow with 2x Sleep 100 built in.
I'd like to test if the Alt+Space menu is open before SendInput s and preferably make sure I'm sending to the menu rather than the main application.

I was unable to reproduce the problem using your method. Perhaps try using Send, SendEvent, SendPlay, SendRaw, #InstallKeybdHook, #UseHook
Alternatively, use Autohotkey's WinMove statement:
This resizes the active window such that the upper left hand corner is at the current mouse position
#^+1::
CoordMode Mouse, screen
id := WinExist("A")
WinGetPos x, y, width, height, ahk_id %id%
MouseGetPos mx, my
neww := width + x - mx
newh := height + y - my
WinMove % "ahk_id" id,, mx, my, neww, newh
return

The menu itself is ahk_class #32768, so waiting for it to exist seems to work for me.
#^+1::
Send , !{space}
WinWait , ahk_class #32768 ,, 1 ; Waits 1s for menu to exist
If !ErrorLevel ; ErrorLevel is 0 if menu exists
Send , s{left}+{up}
Return
Jim U's alternative solution is a more reliable way of doing what you're trying to achieve, but this will make what you currently have work.

Related

AHK script to change RButton Behavior

I want to make a script that would allow me to click once every time I press the mouse, however, if instead of letting go immediately, I hold the RMB for more than 0.25s it would click again on release.
Essentially allowing me to use RMB normally as long as I don't hold it for too long but allowing me to do a double click if held.
This is a work around since my mouse's button gets stuck if I click too fast and I'm not able to get a new one atm.
The purpose of this is to be able to use my mouse on PS and to play the one game i play some times: Black Ops 2 while i save enough for a new mouse. In the context of the game, i want to be able to use Toggle ADS as a base and be able to use the toggle by default by just clicking but be able also do a Hold to ADS with the same button on the fly without changing the game's configuration.
I am not very proficient at AHK and this is all I got so far, holding works fine, however if I don't hold, it does a double click which is annoying.
RButton Down::
Send {Click, Right}
keywait RButton, t.25
if errorlevel
keywait RButton,
Send {RButton Up}
return
You could maybe do some trickery with multiple KeyWaits, but I wouldn't recommend time consuming processing inside hotkey labels in any case due to AHKs single threaded nature.
Here's something very simple I'd recommend instead:
~*RButton::RClickTime := A_TickCount
~*RButton Up::
if (A_TickCount - RClickTime >= 250)
Click, Right
return
So first when we press down RButton (note that there is no "down" state for hotkey names, the key name itself means it being pressed down) we store the current system time with A_TickCount.
And we use the ~ modifier for the hotkey so the keypress itself isn't consumed.
And the * modifier is used so holding down e.g. Ctrl or Shift, etc, wouldn't make the hotkey not work.
Then on RButton release (RButton Up::) we compare the current system time with the stored system time to see if over 250ms passed. If so, we send another right click with Click, Right (don't use a send command here, it isn't really intended for this).
It looks like you're missing some curly braces around your if block; but I think you can implement the right double-click functionality with something as simple as,
RButton::
KeyWait RButton, T.25
numberOfClicks := errorLevel + 1
Send {Click Right %numberOfClicks%}
return
~RButton:: ;*When Right Mouse Button is Down, do the following.*
keywait RButton, T.25 ;*Wait (250 milliseconds) for it to be released.*
if errorlevel { ;*When it exceeds the said time*
keywait RButton ;*Wait for it to be released*
Send, {RButton Up} ;*Send Right Mouse Button up*
}
return

Menu and submenu selection on specific app via Autohotkey

I have a dictionary application in which Ctrl+C does not work, so the only way to copy is to go from the menu, Edit > Copy. I have tried using the following code and variations of it, but it did not work.
!l::
WinActivate, MAGENTA - Dictionaries Explorer II
WinMenuSelectItem, ahk_class TMainForm,, Edit, Copy
return
WinSpy data:
MAGENTA - Dictionaries Explorer II
ahk_class TMainForm
ahk_exe MgDE2.EXE
ahk_pid 2580
Forgetting AHK for a minute, if you just press and release the Alt key (all by itself) what happens?
If the File menu activates (blue box), then you can just send the ALT keystroke followed by directional movement as needed and finally sending ENTER to activate the item
Like this
SendInput {Alt}{Right}{Down}{Enter}
If you needed to go right 4 elements and then down 2 entries you would use this way:
SendInput {Alt}{Right 4}{Down 2}{Enter}

Holding LButton using XButton1 (side button) in AutoHotKey

I need a script where if I hold down XButton1 in my mouse, it auto clicks for me until I release.
I was able to find this script: F1::Click % GetKeyState("LButton") ? "Up" : "Down" but when I change F1 to XButton1 it doesn't seem to hold down like it does with F1.
It appears to only send a left-click down/up once. I think this happens because keypresses and mouse clicks behave differently in that when you hold a key you expect it to repeat after a short delay, whereas if you hold a mouse button you expect it to just stay held and not repeatedly click. Since the XButtons are mouse buttons, they will behave as such, even though the intuitive expected behavior is that of a keypress. Anyway, that aside, we'll just have to make the script longer.
XButton1 Up::bT := false
XButton1::
bT := true
While( bT )
{
Click
Sleep , 50 ; Added sleep to make it a bit more stable (add more if needed)
}
Return

How to obtain textual contents from a window

I have a window that displays a book. In two smaller boxes below, there is page number and volume information of the book that is open. I can get that information easily as follows:
ControlGetText, volume, ThunderRT6TextBox3
ControlGetText, page, ThunderRT6TextBox2
Then my script makes my mouse pointer move to a button. It clicks it, and a new window pops open. In that window, there is more textual information related to the book, such as publisher, name author, edition etc. I want to retrieve that information. But when I try the same strategy it is not working, eg:
ControlGetText, data, RichTextWndClass3
The only difference between the two cases, is that those two small boxes are editable, you can enter text whereas this window is static.
I tried many other options such as:
SendEvent ^a
Which is equivalent to control + a, which should select everything. I tried putting pauses but it would never select. I tried the script to manually double click on that window. It works, and one word gets select like that. Even then SendEvent ^a doesn't do anything.
However, if I do SendEvent ^{insert}, then the selected word gets copied to my clipboard.
I experimented with more combinations:
ControlSend ahk_class ThunderRT6FormDC, ^a
ControlSend ClassNN RichTextWndClass3, ^a
and
ControlSend ThunderRT6FormDC, ^a
ControlSend RichTextWndClass3, ^a
None of them work. All text selection does not manifest itself in that window.
The only alternative remaining for me is to make the script do a manual selection of the entire text. However, this is slow and very ridiculous. Moreover, in Window Spy under the section: Visible Window Text, the text is all there. I tried many other possibilities and I am at the end of my wits. How am I to harvest that text directly?
EDIT--
The text of the window shows in Window Spy under the heading: TitleMatchMode=slow Visible Text, NOT the heading: Visible Window Text
EDIT--
I spoke to you about two windows. The first one in which i get volume and page number. The second one which needs to pop up by pressing a button.
Both these windows have the same class-name:
ahk_class ThunderRT6MDIForm
Is that problematic in any way?
EDIT--
The conclusion is that it is impossible for me to get that text from the second window directly. As such, I opted for the lame, boring manual method. I send out a {shift down} to the active window and then do a click at the bottom of the window. Then I save the selection to my clipboard. It works, but it is just stupid. Please help me find a more elegant solution than this one.
This is the code I used:
ControlGetText, volume, ThunderRT6TextBox3
ControlGetText, page, ThunderRT6TextBox2
Click, 110, 70
sleep 1000
SendInput {shift down}
click 29, 490
SendInput {shift up}
sleep 1000
SendInput, ^{ins}
sleep 100
It is funny to note that real keyboard keys, such as a b c are not possible. But I am able to send a ctrl, shift and an ins. As I noted above, ^c was also giving issues just like ^a was giving issues.
This routine will do the job of getting and returning from the active window the following text sections:
- EdtWindowTextFastVisible
- EdtWindowTextSlowVisible
- EdtWindowTextFastHidden
- EdtWindowTextSlowHidden
MyGetWindowText(ByRef EdtWindowTextFastVisible, ByRef EdtWindowTextSlowVisible, ByRef EdtWindowTextFastHidden,ByRef EdtWindowTextSlowHidden)
{
; Source: https://code.google.com/p/autohotkey-cn/source/browse/trunk/Source/AHK_Window_Info/AHK_Window_Info_v1.7.ahk?r=6
EdtWindowTextFastVisible =
EdtWindowTextSlowVisible =
EdtWindowTextFastHidden =
EdtWindowTextSlowHidden =
WindowControlTextSize = 32767
VarSetCapacity(WindowControlText, WindowControlTextSize)
WinGet, WindowUniqueID, ID, A
;Suggested by Chris
WinGet, ListOfControlHandles, ControlListHwnd, ahk_id %WindowUniqueID% ; Requires v1.0.43.06+.
Loop, Parse, ListOfControlHandles, `n
{
text_is_fast := true
If not DllCall("GetWindowText", "uint", A_LoopField, "str", WindowControlText, "int", WindowControlTextSize)
{
text_is_fast := false
SendMessage, 0xD, WindowControlTextSize, &WindowControlText,, ahk_id %A_LoopField% ; 0xD is WM_GETTEXT
}
If (WindowControlText <> ""){
ControlGet, WindowControlStyle, Style,,, ahk_id %A_LoopField%
If (WindowControlStyle & 0x10000000)
{ ; Control is visible vs. hidden (WS_VISIBLE).
If text_is_fast
EdtWindowTextFastVisible = %EdtWindowTextFastVisible%%WindowControlText%`r`n
Else
EdtWindowTextSlowVisible = %EdtWindowTextSlowVisible%%WindowControlText%`r`n
} Else
{ ; Hidden text.
If text_is_fast
EdtWindowTextFastHidden = %EdtWindowTextFastHidden%%WindowControlText%`r`n
Else
EdtWindowTextSlowHidden = %EdtWindowTextSlowHidden%%WindowControlText%`r`n
}
}
}
;EdtWindowTextFastVisibleFull := ShowOnlyAPartInGui("EdtWindowTextFastVisible", EdtWindowTextFastVisible, 400)
;EdtWindowTextSlowVisibleFull := ShowOnlyAPartInGui("EdtWindowTextSlowVisible", EdtWindowTextSlowVisible, 400)
;EdtWindowTextFastHiddenFull := ShowOnlyAPartInGui("EdtWindowTextFastHidden", EdtWindowTextFastHidden, 400)
;EdtWindowTextSlowHiddenFull := ShowOnlyAPartInGui("EdtWindowTextSlowHidden", EdtWindowTextSlowHidden, 400)
Return
}
There is an autohotkey script that emulates most of the window spy logic. It is called AHK_Window_Info_v1.7.ahk. The nice thing is... you can run it to see if your second window text if visible to this script and if so... the logic needed to pull the information is available inside the script. Here is a link to the webpage and the script is available through SKANs dropbox link on that page. http://www.autohotkey.com/board/topic/8204-ahk-window-info-17/

How Can I Use Upside Numpad?

I am using AutoHotkey. This Program I want to use left side numpad in my script but I couldn't use it.This case is important because I play a game and that game use left side numpad,not right side. (Right side numpad doesn't work in this game)
This is my code;
SendMode Input
~control::
Loop
{
if GetKeyState("e") ; If this statement is true, the user has physically released the F1 key.
break ; Break out of the loop.
send,{Numpad8}
Sleep 200
send,1
Sleep 200
}
return
Any idea?
Edit = I don't know how can I show this problem. How can you understand this Send command press left side's numpad or right side? I play Knight Online game and I can try these methods in the game.Code works or not.But could you try it ?
Here you have all the keys AutoHotkey handles:
http://www.autohotkey.com/docs/commands/Send.htm
Just change send,{Numpad8} to Send,{1}
You can also try to simulate a keypress this way (The last time I used AutoHotkey I had to do it):
Send, {1 down}
Sleep 100
Send, {1 up}
And also, you can try to send the keystrokes directly to the window this way:
wintitle = WINDOW TITLE
Controlsend,,{1 down}, %wintitle%
Sleep 100
Controlsend,,{1 up}, %wintitle%
THe window title can be the starting characters of the window. For example, if the window title is "This is a game", you can set as window title in your script "This is a".