 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
r0lZ
Joined: 21 Apr 2007 Posts: 177
|
Posted: Sun May 13, 2007 11:37 am Post subject: How to retrieve LAST active window? |
|
|
My script needs to determine the active window.
Since the function is launched via the tray menu, the taskbar is activated before I have a chance to retrieve the active window title or ID.
Therefore, I need to retrieve the ID of the window that was active just before the taskbar was clicked.
When there are no Always On Top windows, it's easy.
I can retrieve the topmost window ID with something like that:
| Code: | LastActiveId()
{
WinGet, idlist, list,,, Program Manager
Loop, %idlist%
{
this_id := idlist%A_Index%
WinGetClass, this_class, ahk_id %this_id%
if this_class != Shell_TrayWnd
return %this_id%
}
return 0
}
|
... or I can send !{ESC} to deactivate the toolbar and retrieve the active window ID with WinGet id, ID, A.
But when there are Always On Top windows, neither of these methods work.
LastActiveId() returns always the Always On Top window, even if that window was not active.
The !{ESC} key reactivates always the last window that was activated except any Always On Top window. Therefore, if the Always On Top window was active, another window is activated, and a wrong ID is retrieved.
I have tried to toggle the Always On Top flag of all windows before sending the !{ESC} key (and restore it after):
| Code: | LastActiveID()
{
WinGet, idlist, list,,, Program Manager
numtops = 0
Loop, %idlist%
{
this_id := idlist%A_Index%
WinGetClass, this_class, ahk_id %this_id%
if this_class != Shell_TrayWnd
{
WinGet, exstyle, ExStyle, ahk_id %this_id%
if (ExStyle & 8) ; WS_EX_TOPMOST: Window is always on top
{
numtops += 1
tops%numtops% := this_id
WinSet, AlwaysOnTop, off, ahk_id %this_id%
}
}
}
send !{ESC}
WinGet, id, ID, A
loop %numtops%
{
this_id := tops%a_index%
WinSet, AlwaysOnTop, on, ahk_id %this_id%
}
return id
}
|
No luck! The !{ESC} key still skips the windows that were Always On Top at the time the function is launched, and activates again a wrong window.
Another method that should work (although I haven't tested it) is to use a timer to constantly record the active window ID in a global variable, except when the taskbar is active, and use the recorded ID, but I would like to avoid using a timer for such a (normally) trivial operation.
Hence my question. How can I retrieve the ID of the window that was really active before the tray icon was clicked, regardless if its Always On Top state? _________________ r0lZ |
|
| Back to top |
|
 |
Grumpy Guest
|
Posted: Mon May 14, 2007 9:52 am Post subject: |
|
|
I am sorry for the stupid question, but why don't you use a hotkey instead?
Otherwise, the timer solution is what came to mind, but I see you already thought of this.
Possible solution:
| AHK's Manual, WinGet page wrote: | | List: Retrieves the unique ID numbers of all existing windows [...] Windows are retrieved in order from topmost to bottommost (according to how they are stacked on the desktop). |
|
|
| Back to top |
|
 |
r0lZ
Joined: 21 Apr 2007 Posts: 177
|
Posted: Mon May 14, 2007 2:09 pm Post subject: |
|
|
I don't want to be forced to use an hotkey for each action available in the tray menu of my script, because there is a big risk of conflicts, and I prefer to use some functions with the mouse. Some actions have a configurable hotkey, and, in this case, of course, there is no problem.
Although it's not easy to do because there are a lot of special cases to avoid, I've just finished programming my app with the timer trick. I don't like that too much, but it works, and the timer method has the advantage that the tray menu can be configured dynamically. I can now disable the useless menu entries when there is no active window.
Thanks for the WinGet's List hint, but, of course, I've tried that also. Unfortunately, that doesn't work neither, as the Always On Top windows are also on top of this list, even when they are not active. (BTW, the Windoze taskbar is always at the very top of the list, but of course, it is easy to skip it.)
It seems that "WinGet, id, ID, A" retrieves always the first window in that list that has NOT the Always On Top property. It's useful in many cases, but unfortunately not for me!
Thanks anyway! _________________ r0lZ |
|
| Back to top |
|
 |
Grumpy Guest
|
Posted: Mon May 14, 2007 2:30 pm Post subject: |
|
|
A stupid workaround would be to have a hotkey to capture the currently active window ID: the user would have to hit the hotkey, then to go to the tray menu.
OK, that's stupid... :o) |
|
| Back to top |
|
 |
r0lZ
Joined: 21 Apr 2007 Posts: 177
|
Posted: Mon May 14, 2007 2:38 pm Post subject: |
|
|
Hum, yes, that's not very smart!
Currently, my method works fine, although the counter consumes some CPU power and memory (as I need several global variables) but it's not really a problem. Even it it's not an elegant way to do it, I'm happy with this method. _________________ r0lZ |
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 4511 Location: Belgrade
|
Posted: Wed May 16, 2007 9:25 pm Post subject: |
|
|
I have the very same problem.
My app racts on hotkey and on tray click. As it operates depending on the active window in time when hotkey is pressed, I lose focus to id when tray is accessed. I use currently !ESC but it has side efects that right click doesn't work on the menu I show. This doesn't happen when I remove !ESC.
So, I seek the way to get the last active window without changing focus.
I don't have any problems with !ESC though and always on top wins. _________________
 |
|
| Back to top |
|
 |
SHiLLySiT
Joined: 17 May 2007 Posts: 12
|
Posted: Thu May 17, 2007 2:18 am Post subject: |
|
|
You could always set up the menu that you have in the tray as a right click pop up menu. I have this set up in one of my programs.
| Code: |
DetectHiddenWindows, on ;just a precaution
+RButton:: ;hold shift and right click.
WinGetActiveTitle, win ;get current title
MouseGetPos, mousex, mousey ;get current mouse position
Menu, desk, Add, MenuItem, Handler
Menu, desk, Show, %mousex%, %mousey%
return
Handler:
msgbox title %win%
return |
|
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 4511 Location: Belgrade
|
Posted: Thu May 17, 2007 12:01 pm Post subject: |
|
|
That will not be possible in this case. _________________
 |
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 4511 Location: Belgrade
|
Posted: Thu May 17, 2007 2:44 pm Post subject: |
|
|
After PM communication with Sean, we discovered one way that in first test worked for me :
| Code: | OnMessage(WM_ACTIVATEAPP := 0x1C, "OnActivate")
OnActivate() {
msgbox % DllCall("GetForegroundWindow")
} |
BTW, it seems that this problem is well known in scripting environments. I got AU3 solution on SysInternals forum. AutoIt users had the very same problem.
They used variation of r0lZ WinGet, , list but I didn't try to understand the code much as it looks like non-reliable to me (probably suffers from same "always on top" syndroms). Check it out here _________________
 |
|
| Back to top |
|
 |
r0lZ
Joined: 21 Apr 2007 Posts: 177
|
Posted: Thu May 17, 2007 3:05 pm Post subject: |
|
|
Thanks for your investigations, majkinetor!
I'll try the WM_ACTIVATEAPP method soon. _________________ r0lZ |
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 4511 Location: Belgrade
|
Posted: Fri May 18, 2007 7:19 am Post subject: |
|
|
Well, bad news. I did more througly tests of WM_ACTIVATEPP.
It really works, sometimes, but again, not always.
The problem seems to be this: shellWnd is container for tray. When you click the tray, first shell takes focus, then your app. Sometimes, here, even DesktopX which keeps my tray is involved... Then, I get on my machine 5 times right window, and 6th time DesktopX or ShellWnd...
well... it was nice try. _________________
 |
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 4511 Location: Belgrade
|
Posted: Fri May 18, 2007 7:19 am Post subject: |
|
|
Well, bad news. I did more througly tests of WM_ACTIVATEPP.
It really works, sometimes, but again, not always.
The problem seems to be this: shellWnd is container for tray. When you click the tray, first shell takes focus, then your app. Sometimes, here, even DesktopX which keeps my tray is involved... Then, I get on my machine 5 times right window, and 6th time DesktopX or ShellWnd...
well... it was nice try.
!ESC works the best so far. Acctually, I don't have any problem with it, it never made a mistake, ecept side effect is that my menu loses focus... _________________
 |
|
| Back to top |
|
 |
Sean
Joined: 12 Feb 2007 Posts: 2462
|
Posted: Fri May 18, 2007 8:02 am Post subject: |
|
|
| majkinetor wrote: | | The problem seems to be this: shellWnd is container for tray. When you click the tray, first shell takes focus, then your app. Sometimes, here, even DesktopX which keeps my tray is involved... Then, I get on my machine 5 times right window, and 6th time DesktopX or ShellWnd... |
If that's the issue, you may try to give WS_EX_NOACTIVATE ExStyle to the taskbar.
But, I'm not sure if it won't do more harm than good.
| Code: | | WinSet, ExStyle, +0x08000000, ahk_class Shell_TrayWnd ; WS_EX_NOACTIVATE |
|
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 4511 Location: Belgrade
|
Posted: Fri May 18, 2007 8:58 am Post subject: |
|
|
Acctually, you can't detect how many intermidate applications (shell, make-up, whatever) is going to be activated when the user presses tray icon... They will all be hidden though.. perhaps that can help... if ForeGroundWindow is not visible, don't update global var ... worth trying....
Interesting idea.
I just got another side effect of tray. This problem appers to me in Favmenu which sets the path in common dialogs. So, using WM_ACtivateAPP it works sometimes, but then interesting problem appears. Favmenu does change the path in Open/Save dialog (OS) but path is changed only AFTER i click on the OS window. So, I can use tray icon, select folder I want to switch and it does that, but I can click in, lets say 10 seconds OS and it will change it then. Something is blocking.. don't know why.. I tried to eliminate tray activation from the story so i did this:
| Code: | TrayHandler:
Send !{Esc}
SetTimer ActivateHotKey, 100
return
ActivateHotKey:
SetTimer, ActivatehotKey, off
Favmenu_Show() ; show the menu
return |
I was hopping that this will fake windows user is using a hotkey which doesn't have a problem, but it didn't... The problem here is that MMenu loses focus on subsequent call after tray is clicked ?!. So I did only this:
| Code: | FavMenu_TrayDefault(){
Send, !{ESC}
} |
This was returning the focus to OS. Then I called a hotkey. Menu didnt' have a focus. If I reactivate the focus clicking something, subsequent menus had focus and I just can't activate it.
WinActivate, ahk_class #32768 always hide the menu. _________________

Last edited by majkinetor on Fri May 18, 2007 9:13 am; edited 1 time in total |
|
| Back to top |
|
 |
r0lZ
Joined: 21 Apr 2007 Posts: 177
|
Posted: Fri May 18, 2007 9:11 am Post subject: |
|
|
| majkinetor wrote: | | !ESC works the best so far. Acctually, I don't have any problem with it, it never made a mistake, ecept side effect is that my menu loses focus... |
Hum, seems you're right. If I use a simple script to test the !{ESC} trick, it works. Here it is: | Code: | #NoEnv
SendMode Input
#persistent
#singleinstance force
menu tray, add
menu tray, add, Test !ESC, test_esc
return
test_esc:
send !{ESC}
winGet id, ID, A
winGetTitle title, ahk_id %id%
MsgBox %id%`n%title%
return
|
But when I include that in my application, it doesn't work! I wonder why. I will check again. _________________ r0lZ |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|