AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

How to retrieve LAST active window?
Goto page Previous  1, 2, 3, 4
 
Reply to topic    AutoHotkey Community Forum Index -> Ask for Help
View previous topic :: View next topic  
Author Message
majkinetor



Joined: 24 May 2006
Posts: 4511
Location: Belgrade

PostPosted: Wed May 23, 2007 11:08 am    Post subject: Reply with quote

It would be good if you could create function GetActiveWidowId that we can use when tray icon is clicked or the one that will set shell hooks needed for lastactivewin_id global, so I can try your findings imediately.
_________________
Back to top
View user's profile Send private message
r0lZ



Joined: 21 Apr 2007
Posts: 177

PostPosted: Wed May 23, 2007 12:55 pm    Post subject: Reply with quote

That was my intention, but I would like to improve it before, and I haven't much time these days. I will post it in some days. Sorry.
But the method is based on the HSHELL_WINDOWACTIVATED tip posted by Skan above.
_________________
r0lZ
Back to top
View user's profile Send private message
r0lZ



Joined: 21 Apr 2007
Posts: 177

PostPosted: Wed May 23, 2007 9:14 pm    Post subject: Reply with quote

OK, I,ve finally found some time to do a demo script, with what I've learned.

The script demonstrate how to get the ID of the window that was active before the user clicked on the tray menu to call a function via the tray menu. (The solution of the subject of this thread.)

It demonstrates also how to refresh the tray menu dynamically to take the current active ID properties into account.

In passing, it shows also how to process the middle mouse button and X buttons 1 and 2 clicks over the tray icon.

Here it is:
Code:
; *** initialization
#Persistent
#SingleInstance force
#NoEnv
SendMode Input

Menu, Tray, Add
last_prop_menu_label = Info: -
Menu, Tray, Add,     %last_prop_menu_label%, LabWinInfo
Menu, Tray, Default, %last_prop_menu_label%
Menu, Tray, Disable, %last_prop_menu_label%
Menu, Tray, Click, 1

LastActiveID := ActiveId()

Gui +LastFound
DllCall( "RegisterShellHookWindow", UInt,WinExist() )
MsgNum := DllCall( "RegisterWindowMessage", Str,"SHELLHOOK" )
OnMessage( MsgNum, "ShellMessage" )

OnMessage(0x404, "TrayMessage")

OnExit, CleanExit

Return


; exit app
CleanExit:
   OnExit,
   DllCall("DeregisterShellHookWindow", UInt,hWnd)
ExitApp

; Shell hook
ShellMessage(wParam,lParam)
{
   Global LastActiveID
   If (wParam=4 And checkNormalWin(lParam)) {
      LastActiveID := lParam
   }
}

; called whenever the mouse pointer is over the tray icon
TrayMessage(wParam, lParam)
{
   global xbutton, LastActiveID
   if lParam = 0x204   ; WM_RBUTTONDOWN
   {
      ; refresh the tray menu before it is displayed
      RefreshMenu(LastActiveID)
   }
   if lParam = 0x208   ; WM_MBUTTONUP
   {
      ; executed when the tray icon is clicked with the middel mouse button
      MsgBox Middle mouse button
   }
   if (lParam=524)  ; lParam = 524: Up message for XButton1 AND 2!
   {
      if xbutton = 1
      {
         ; executed when the tray icon is clicked with the Xbutton1
         MsgBox X Button 1
      }
      else
      {
         ; executed when the tray icon is clicked with the Xbutton2
         MsgBox X Button 2
      }
   }
}
; we need to retrieve the XButton number using those hotkeys
XButton1::
   xbutton=1
   Send {XButton1 Down}
return
XButton1 Up::
   xbutton=1
   Send {XButton1 Up}
return
XButton2::
   xbutton=2
   Send {XButton2 Down}
return
XButton2 Up::
   xbutton=2
   Send {XButton2 Up}
return

; return the windowID passed in argument if the window is not a system window,
; otherwise, return 0
checkNormalWin(wid)
{
   ifWinNotExist ahk_id %wid%
      return 0
    WinGetClass, class, ahk_id %wid%
   if class in Shell_TrayWnd,Progman,Static,tooltips_class32,SysShadow
      return 0
   return %wid%
}

;; return the windowID passed in argument if the window appears
;; in the Alt-Tab menu and exists, otherwise, return 0
;checkNormalWin(wid)
;{
;   ifWinNotExist ahk_id %wid%
;      return 0
;   WinGet, es, ExStyle, ahk_id %wid%
;   if ((!DllCall("GetWindow","uint",wid, "uint",4) and !(es & WS_EX_TOOLWINDOW)) \
;         or (es & WS_EX_APPWINDOW))
;      return %wid%
;   return 0
;}

; return the window ID of the currently active window,
; or 0 if the active window is not a "normal" window.
ActiveId()
{
   WinGet, wid, ID, A
   return checkNormalWin(wid)
}

; refresh the menu when the user clicks on the tray icon
RefreshMenu(wid)
{
   global last_prop_menu_label
   wid := checkNormalWin(wid)
   if (wid > 0)
   {
      WinGetTitle, title, ahk_id %wid%
      if title =
         title = Untitled
      if (strlen(title) > 22)
         title := SubStr(title, 1, 20)"..."
      
      if last_prop_menu_label != Info: %title%
      {
         Menu, Tray, Rename, %last_prop_menu_label%, Info: %title%
         last_prop_menu_label = Info: %title%
         Menu, Tray, Default, %last_prop_menu_label%
         Menu, Tray, Enable, %last_prop_menu_label%
      }
   }
   else
   {
      if last_prop_menu_label != Info: -
      {
         Menu, Tray, Rename, %last_prop_menu_label%, Info: -
         last_prop_menu_label = Info: -
         Menu, Tray, Default, %last_prop_menu_label%
         Menu, Tray, Disable, %last_prop_menu_label%
      }
   }
}

; demo function
LabWinInfo:
   WinInfo(LastActiveID)
return
WinInfo(wid)
{
   WinGetTitle, title, ahk_id %wid%
   WinGetClass, class, ahk_id %wid%
   WinGetPos, xpos, ypos, width, height, ahk_id %wid%
   WinGet, processname, ProcessName, ahk_id %wid%
   WinGet, pid, PID, ahk_id %wid%
   WinGet, style, Style, ahk_id %wid%
   WinGet, exstyle, ExStyle, ahk_id %wid%
   MsgBox, 262208, TrayDesktop: Active window info, Window title :  %title%`nWindow class :  %class%`nWindow ID :  %wid%`nWindow position :  %xpos%`,%ypos%`,  Size :  %width% x %height%`nWindow style :  %style%`,    ExStyle :  %exstyle%`nProcess :  %processname%    (PID = %pid%)
}

Note that there are 2 versions of checkNormalWin(). Currently, I prefer the first one, that filters the windows based on a list of window classes. If you prefer to process only the root windows, you should replace the current function by the one that is commented out in the code.

Sorry, there are very few comments, but I haven't enough time to do it better.

A huge thanks to the contributors!
_________________
r0lZ
Back to top
View user's profile Send private message
majkinetor



Joined: 24 May 2006
Posts: 4511
Location: Belgrade

PostPosted: Wed May 23, 2007 11:41 pm    Post subject: Reply with quote

Ah, now I see.

I don't use standard task bar and tray icon.
ObjectBar is displaying them. Check it out here:


So, when I click the tray icon, first ObjectBar gets focus. This makes entire procedure not working. When I disable ObjectBar it doesn't happen.

I tried to exclude the class but nothing..
I will see what I can do, but I suspect ppl using different themes will have the same problems.

http://ic3.deviantart.com/fs8/i/2005/356/a/a/My_desktop_by_r_moth.jpg
_________________
Back to top
View user's profile Send private message
r0lZ



Joined: 21 Apr 2007
Posts: 177

PostPosted: Thu May 24, 2007 7:48 am    Post subject: Reply with quote

I suppose you have to install another hook. Maybe Skan can help...
Or use the timer method. It works nicely, although it consumes some CPU power.
Of course, with both methods, you have to exclude all task/object bars.
I wonder also if the hook method works under Vista.

If I ever distribute my program publicly, I guess I have to provide both methods.
_________________
r0lZ
Back to top
View user's profile Send private message
r0lZ



Joined: 21 Apr 2007
Posts: 177

PostPosted: Thu May 24, 2007 10:46 am    Post subject: A problem with the hook method Reply with quote

I've found another interesting thing.

When the root window of an application is not visible (but appears in the taskbar) and another "normal" window contains the GUI (and is not in the taskbar), it is possible to discover if the active window has a parent that is invisible, and process the parent as well as the GUI window.

For the two applications I have that use this method (AlZip and MailWasher), the root window has a size of 0x0. It is therefore easy to exclude it. And when a normal window is active, it is relatively easy to check if its parent is invisible, with:
Code:
InvisibleParent(wid)
{
   parent := DllCall("GetWindow", "uint",wid, "uint",4)
   if parent = 0
      return 0
   WinGetPos,,, width, height, ahk_id %parent%
   if (width = 0 and height = 0)
      return %parent%
   return 0
}


OK, so, I decided to improve my app to process both windows at once, when the parent of the active window is invisible.

That works very well when the active ID is retrieved with WinGet, wid, ID, A, but as we know, we can't do that if the main function is called via the tray icon. Therefore, we have to use the hook method.

The interesting thing is that the hook method doesn't work in this case. The hook finds well when the invisible parent is activated (for example when the window is opened for the first time, or when the user clicks on the button of the taskbar), but doesn't find the normal GUI window when it is activated by a click on the window. It finds the parent instead! Seems the invisible parent is always activated instead of the GUI (although the GUI window has the appearance of an active window!)

Also strange: If you hide the invisible root window (with WinHide), the taskbar button disappears and the remaining GUI window is then processed normally by the hook function!

I don't understand!
Maybe I will revert to the timer method, as it is possible to use WinGet, wid, ID, A to avoid this problem...
_________________
r0lZ
Back to top
View user's profile Send private message
emmanuel d



Joined: 29 Jan 2009
Posts: 436
Location: Belgium

PostPosted: Mon May 09, 2011 5:01 pm    Post subject: Reply with quote

I am doing something less complex to toggle the gui on tray click, like this:
Code:
#Persistent
Menu, M, Add, Note that this is the middle mouse button, Exit
Menu, M, Add, NOT the tray menu., Exit
Menu, L, Add, Note that this is the left button, Exit
Menu, L, Add, NOT the tray menu., Exit
Menu, Tray, Add, Note that this is the Right button, Exit 
Menu, Tray, Add, The tray menu., Exit
Gui, add,text, w100 h100,test
; name of the script = TrayAnimation.ahk
Gui, show,w100 h100,TestTray
OnMessage(0x404, "AHK_NOTIFYICON")
return
AHK_NOTIFYICON(wParam, lParam) { ; http://www.autohotkey.com/forum/post-172559.html#172559
   static text:="", ActiveWinTitle
   if (lParam = 0x200) { ; WM_MOUSEMOVE = 0x200
      WinGetActiveTitle, tempActiveWinTitle
      ActiveWinTitle:= tempActiveWinTitle ? tempActiveWinTitle : ActiveWinTitle
      return 0
      }
    if (lParam = 0x205) { ; WM_RBUTTONUP
      Menu, tray, Show ; Right mouse button menu
      return 0
      }
   if (lParam = 0x202) { ; WM_LBUTTONUP
      if (ActiveWinTitle="TestTray") {
         Gui, Hide
         ActiveWinTitle:=""
         ; WinActivate   ; activate the last used window (does not work, that is the tray)
      } else {
         Gui, show
         ActiveWinTitle:="TestTray"
         }
      return 0
      }
   if (lParam = 0x208) { ; WM_MBUTTONUP
         Menu, M, Show ; Midlle mouse button menu
        return 0
      }
   }
GuiClose:
   Gui, Hide
   return
Exit:
   ExitApp
   Return


_________________
Stopwatch
emdkplayer
http://www.autohotkey.com/forum/viewtopic.php?p=306819

the code i post falls under the:
WTFYW license
, wich meens its free to use
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    AutoHotkey Community Forum Index -> Ask for Help All times are GMT
Goto page Previous  1, 2, 3, 4
Page 4 of 4

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group