Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate

[Resolved] Activate last active window - what is wrong?

  • Please log in to reply
7 replies to this topic
  • Moderators
  • 1317 posts
  • Last active: Mar 28 2015 08:33 PM
  • Joined: 18 May 2010
Hey all. I'm proud I *THINK* I managed to create a functioning script pretty much from scratch. Not really advanced, but this script should add an interesting function to windows. By pressing [Win]+Z, you will simply activate the last active window. For example, I may now want to copy some text from the AHK-forums to a texteditor. I would then select the text, copy, bring up the texteditor, and return to AHK-forums simply by pressing [Win]+Z. As a bonus, if you are jumping between two windows, you can always jump back to the previous window, so in my example - I could then jump back to the texteditor.

A bit faster than alt-tabbing, without doubt. I may provide more examples of its' uses if you don't agree with me.

Anyway, the code seems flawed. I thought I had finally managed to make it, as the code works pretty flawlessly (100% accuracy) in my testing. However, when dealing with maximized windows it fails. In order to try "as it should be", simply have a couple of non-maximized windows and try it out. Activate another window, then [Win]+Z to go back to the previously active one. What should I do? I don't wanna minimize or maximize windows unless needed

; SCRIPT FUNCTIONALITY Activates the last active windows
#SingleInstance Force
active_ID_old := 1
active_ID_present := 2
active_ID_stored := 3
; If variables start undefined, I seem to get problems - thus the above definitions
loop {
WinGet, active_ID_present, ID, A	
	IfNotEqual, active_ID_old, %active_ID_present%
		active_ID_stored := active_ID_old ; The "IfNotEqual" part may be unneeded, but it's there just in case. When an "old" and a "new" window are present, the function "stores" the "old" window for later use

WinGet, active_ID_old, ID, A
WinWaitNotActive ; The loop only restarts when the user switches window
IfWinExist ahk_id%active_ID_stored% ; Again, "just in case". I hoped to eliminate the problem with "no window" being active.
; WinMinimize ahk_id%active_ID_present% <--- Not needed?
WinActivate ahk_id%active_ID_stored%
WinShow ahk_id%active_ID_stored%
; WinMaximize ahk_id%active_ID_stored% <---- Not needed?
active_id_stored := active_ID_old

;MsgBox, Trying to recall %active_ID_stored%

Pardon the comments, if you're in a good texteditor where comments are in a different color, I hope you might find them helpful.

Grateful for assistance.

  • Members
  • 901 posts
  • Last active: Jul 08 2011 02:12 PM
  • Joined: 29 Feb 2008
Honestly, I still think that alt-tabbing is faster. alt-tab to get to the last window, alt-tab-tab to get to the second to most recent window, alt-tab-tab-tab to get to the third most recent window... you get the picture.

does this not do exactly what you want?:
#Z::SendInput !{Tab}

Never be ashamed of commenting your code! It makes debugging so much easier. The more comments, the better.

  • Members
  • 901 posts
  • Last active: Jul 08 2011 02:12 PM
  • Joined: 29 Feb 2008
I simplified your code (and it now works with maximized windows):

; SCRIPT FUNCTIONALITY Activates the last active windows
#SingleInstance Force
previous_ID := 0

	; get the current window's handle
	WinGet, current_ID, ID, A
	; wait until a new window is activated
	WinWaitNotActive, ahk_id %current_ID%
	; save the previous window's handle for later
	previous_ID := current_ID

	; activate the previous window
	WinActivate ahk_id %previous_ID%
	; note that the earlier loop will take care of updating previous_ID.  
	; WinWaitNotActive doesn't care if it was this script or the user that caused the active window to change...
	; it is just looking at the handle of the current window.

;#Z::SendInput !{Tab}

The big problems in your original code (that were causing the maximized window problem) were:
active_id_stored := active_ID_old

WinGet doesn't set the last active window, so you need to specify which window handle you actually want it to wait on. And there was no need to update your ids again after switching to the last window, because the loop was already handling that.

  • Administrators
  • 3832 posts
  • Last active: Today, 11:23 AM
  • Joined: 21 Aug 2006

Honestly, I still think that alt-tabbing is faster..

In this case simple is better ;)

  • Members
  • 424 posts
  • Last active: Apr 05 2012 01:18 AM
  • Joined: 23 Dec 2006
Btw, Windows already has a hotkey for that, it's Alt-Esc.

  • Moderators
  • 2836 posts
  • Last active: May 25 2015 06:44 AM
  • Joined: 24 May 2009
Here's a more complex solution using the windows/buttons present on the ToolBar & comparing them to the Z-Order of windows:
[color=DarkRed]SetTitleMatchMode[/color], 2

TrayWnd := list := [color=CornFlowerBlue]""[/color], n := 0

; get the Task Bar buttons/windows
	[color=DarkRed]ControlGet[/color], hwnd, hwnd, , ToolbarWindow322, ahk_class Shell_TrayWnd
	ToolBar := COM_AccessibleObjectFromWindow( hwnd )
	[color=DarkRed]Loop[/color], % ToolBar.accChildCount {
		[color=DarkRed]WinGet[/color], hwnd, id, % ToolBar.accName( [color=OrangeRed]A_Index[/color] )
		[color=DarkRed]If[/color] hwnd
			TrayWnd .= hwnd [color=CornFlowerBlue]"`n"[/color]

[color=darkred]IfWinActive[/color], ahk_class WorkerW
	n++ ; don't skip the first window

; get the Z-Order of windows & compare to Tool Bar
	[color=DarkRed]WinGet[/color], hwnd, list
	[color=DarkRed]Loop[/color], %hwnd%
		[color=DarkRed]If[/color] [color=DarkRed]InStr[/color]( TrayWnd, hwnd%[color=OrangeRed]A_Index[/color]% )
			[color=DarkRed]If[/color] ( n ) { ; If ( n = 1 ) then we skipped the Active Window
				n := hwnd%[color=OrangeRed]A_Index[/color]%
			} [color=DarkRed]Else[/color] n++

[color=DarkRed]WinActivate[/color], ahk_id %n%
**This example uses AHKL & COM_L**

  • Moderators
  • 1317 posts
  • Last active: Mar 28 2015 08:33 PM
  • Joined: 18 May 2010
Thanks for the feedback, pointers and script. Jethrow, your script requires extra libraries I bet, so haven't had the opportunity to try it.

@Rapte_Of_Suzaku: Thanks! While I tried your script earlier, it seemed to lack some function, but it now works perfectly like I imagined.

I did NOT know that alt+tab always went to the previous windows. Neither did I know that alt+esc did something similar.

However, these keybinds are not without problems.

- Alt+tab sometimes goes to another window, and it is non-intuitive. It also may require user attention to make sure the goal windows is appropiate. In addition, one must be careful not to hold the tab key for too long, or it will start cycling.
- Alt+esc cycles through active windows one-and-one (pretty much like a singleclick alt+tab, I imagine).
- However, neither of those work in combination with Win+D. If you have minimized your windows, you won't get your "previously active window" back. With the code I had in mind, you can easely Win+D, then bring your window back with an intuitive Win+Z.

So, after all, I think I'll be using your script Rapte_Of_Suzaku, credit to you. Looks very much like the base I made, but much cleaner and obvioussly without that error you pointed out.

  • Members
  • 1 posts
  • Last active: Oct 13 2014 09:13 AM
  • Joined: 12 Oct 2014

Hey thank you so much for this script sumon and Rapte_Of_Suzaku.


Was exactly what I was looking for.


Can I please request a small improvement to this script:


when you minimize a single window using default windowkey+downarrow and then use this script twice(just spamming), the first time it works fine, but second time pressing it kind of loses the window from its focus. so you cannot minimize it any more using windowkey+downarrow. Let me demonstrate what I mean:


So the problem:

1) have a non-maximised window open

2) minimize by pressing windowkey+downarrow

3) maximize by pressing this script key

4) minimize by pressing windowkey+downarrow

5) maximize by pressing this script key

6) maximize by pressing this script key

7) PROBLEM: this doesnt work anymore: minimize by pressing windowkey+downarrow


So the desired functionality would be that this script is spammable if possible please:)