GUI - want WindowID of active window *before* button is pressed

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
Sticky

GUI - want WindowID of active window *before* button is pressed

12 Apr 2017, 21:51

---+ BRIEF

When I press a button in an AutoHotKey GUI object, the active window is the GUI object itself. I.e. the button press changes the active window.

Q: is there any way I can determine the windowID of the window that was active BEFORE the button was pressed?

Is there a history of active window IDs? Or a way to construct one, e.g. by hooking the "windows activate" event for all windows?

---+ DETAIL

I am writing what I call a "GUI extension", specifically a buttonpad.

In AHK terms, a GUI, with buttons, such that when you press a button (typically on a touchscreen, although I have done this with mice before) a particular command/key/mouse sequence is sent to one or more particular applications (app windows, whatever).

E.g. I might have a button labelled "Courier" that sends "{alt}ofCourier{Return}" to Notepad,
and another buttion labelled "Times New Roman" that sends "{alt}ofTimesNewRoman{Return}" to Notepad.

Rather like https://www.quadro.me/, except that Quadro requires a separate iPad, whereas I want to take advantage of having a touchscreen. When docked, a fairly big touchscreen - a Windfows Surface Book - with several (2-3) physically much larger external displays.

Basically, hotkeys - except that rather than pressing keys while the target window is active, press buttons in the AHK GUI object (which seems to be a window), and send it to a different target window.

I have this working well enough, if I know the target window.


However, when using Quadro I have often sent generic commands to the currently active window. I.e. the currently active window on the target machine, the Mac or PC. This works in Quadro because the buttonpad (which Quadro calls a palette) is on a different device, the iPad, so pressing a Quadro button does not change the active window on the target machine.


However, I want to do away with the need for a separate physical device, and just use my PC's touchscreen as its own buttonpad.

PROBLEM: when I touch a button in the AutoHotKey GUI object, the active window seems to change to ... the AutoHotKey GUI object. E.g. WinGetActiveTitle returns the title of my AHK gui object, not the window that I was in before I touched my GUI button.

Q: is there any way of knowing the WindowID of the window BEFORE my GUI window was activated?

More generally: is there any way to create a history of window activations? Depth 0 is what we seem to have now - just the currently active window. Depth 1 is what I want, so that I can send generic commands to the window active before the buttonpad was touched. Depth 2 and deeper might allow grammar - e.g. touch window1 containing a file, then window2 containing an app, then window3 ..., finally a GUI button saying "create a pipeline".

Q: if there is not an existing history, is there a way to hook and record window activation events?

Q: is there a way to configure the AutoHotKey GUI object so that it can have its button pressed, but not be the active window?

Thanks for any other advice...

---

I just thought of a strange way of doing what I want: I could have the AutoHotKey GUI object run in its own virtual machine. Unfortunately, to do that I would have to dedicate a display to that VM; the nice, convenient, VM interfaces which place the guest VM in a window on the host's window manager would suffer the same active window switching problem.

Besides, this would be taking a very big hammer for a fairly minor issue. VMs are a pain to administer - one of the reasons I am writing this tool is to avoid the need to run Parallels on a MacBook.
User avatar
noname
Posts: 516
Joined: 19 Nov 2013, 09:15

Re: GUI - want WindowID of active window *before* button is pressed

13 Apr 2017, 06:29

You can have a button pressed without activating the Gui:

WS_EX_NOACTIVATE = E0x08000000

example:

Code: Select all

Gui, +AlwaysOnTop +E0x08000000       
Gui, Add, Button,  w50 h50 gtest,title
Gui,show,w100 h100
return

test:
WinGetActiveTitle, title
tooltip %title%
return

guiclose:
esc::
exitapp

You can have a list with all the preceding titles of activated windows using an EventHook.

This is an adapted code originally made by Kon:

Code: Select all

;  code adapted from kon' code   https://autohotkey.com/boards/viewtopic.php?t=8448

OnExit, UnHook
EVENT_SYSTEM_FOREGROUND           := 0x0003
Hook := DllCall("SetWinEventHook"
    , "UInt",   EVENT_SYSTEM_FOREGROUND                                          ;_In_  UINT eventMin
    , "UInt",   EVENT_SYSTEM_FOREGROUND                                          ;_In_  UINT eventMax
    , "Ptr" ,   0x0                                             ;_In_  HMODULE hmodWinEventProc
    , "Ptr" ,   RegisterCallback("WinEventProc")                ;_In_  WINEVENTPROC lpfnWinEventProc
    , "UInt",   ExcelPID                                        ;_In_  DWORD idProcess
    , "UInt",   0x0                                             ;_In_  DWORD idThread
    , "UInt",   WINEVENT_OUTOFCONTEXT|WINEVENT_SKIPOWNPROCESS)  ;_In_  UINT dwflags
return

WinEventProc(hWinEventHook, event, hwnd, idObject, idChild, dwEventThread, dwmsEventTime) {
    static list:=""
    if (event=0x0003)
    WinGetTitle, WinTitle, ahk_id %hwnd%
    if wintitle
    list .="title=  " wintitle "handle=   " hwnd "`n"
tooltip %list%
    return
}


esc::
UnHook:
DllCall("UnhookWinEvent", "Ptr",Hook)
ExitApp
Sticky
Posts: 10
Joined: 12 Apr 2017, 22:08

Re: GUI - want WindowID of active window *before* button is pressed

13 Apr 2017, 11:58

Many thanks, @noname.

I think that I will chase the

Code: Select all

WS_EX_NOACTIVATE 0x08000000L
first, since I think it is more likely to be safe than the activated window history.

Although anything that involves asynchronous window activations is possibly a security problem.

Below I post some details for anyone else chasing down this sort of thing.

Sorry for bad formatting. (A new forum, a new format syntax.) Must get to work; I will come back and correct formatting later.

---+ TL;DR

Code: Select all

Gui, +AlwaysOnTop +E0x08000000
I was going to ask "Where is that in the docs?", but I found it - posting just for anyone else looking:

First,

Code: Select all

Gui, +/-Option1 +/-Option2 ...
The GUI doc says, at top
[indent=]
GUI
Creates and manages windows and controls. Such windows can be used as data entry forms or custom user interfaces.

Code: Select all

Gui, sub-command [, Param2, Param3, Param4]
[/indent]

The construct

Code: Select all

Gui, +/-Option1 +/-Option2 ...
does not seem to match the pattern

Code: Select all

Gui, sub-command [, Param2, Param3, Param4]
- what is the subcommand?

But then later (much later, must scan through much other material), I see the section titled
[indent=]

Code: Select all

Gui, +/-Option1 +/-Option2 ... ¶
One or more options may be specified immediately after the GUI command. For performance reasons, it is better to set all options in a single line, and to do so before creating the window (that is, before any use of other sub-commands such as Gui Add).
[/indent]

i.e. no subcommand. This section is linked to via the following in the mini-table-of-contents for GUI
[indent=]Options and styles for a window: Sets various options for the appearance and behavior of the window.
[/indent]

And within that:
[indent=]
(Unnamed ExStyle): Specify a plus or minus sign followed immediately by the letter E and a decimal or hexadecimal extended style number. For example, +E0x40000 would add the WS_EX_APPWINDOW style, which provides a taskbar button for a window that would otherwise lack one. Although the other extended styles are not documented here (since they are rarely used), they can be discovered by searching for WS_EX_APPWINDOW at http://www.microsoft.com.[/indent]

And on https://msdn.microsoft.com/en-us/librar ... s.85).aspx

[indent=]WS_EX_NOACTIVATE
0x08000000L
A top-level window created with this style does not become the foreground window when the user clicks it. The system does not bring this window to the foreground when the user minimizes or closes the foreground window.
To activate the window, use the SetActiveWindow or SetForegroundWindow function.
The window does not appear on the taskbar by default. To force the window to appear on the taskbar, use the WS_EX_APPWINDOW style.[/indent]

Thanks. Exactly what I needed to know.

The following also appear relevant

[indent=]WS_EX_PALETTEWINDOW
(WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST)
The window is palette window, which is a modeless dialog box that presents an array of commands.

WS_EX_TOOLWINDOW
0x00000080L
The window is intended to be used as a floating toolbar. A tool window has a title bar that is shorter than a normal title bar, and the window title is drawn using a smaller font. A tool window does not appear in the taskbar or in the dialog that appears when the user presses ALT+TAB. If a tool window has a system menu, its icon is not displayed on the title bar. However, you can display the system menu by right-clicking or by typing ALT+SPACE.

WS_EX_TOPMOST
0x00000008L
The window should be placed above all non-topmost windows and should stay above them, even when the window is deactivated. To add or remove this style, use the SetWindowPos function.

WS_EX_CONTROLPARENT
0x00010000L
The window itself contains child windows that should take part in dialog box navigation. If this style is specified, the dialog manager recurses into children of this window when performing navigation operations such as handling the TAB key, an arrow key, or a keyboard mnemonic.

[/indent]

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Descolada, Google [Bot], j4byers and 128 guests