AutoHotkey Community

It is currently May 25th, 2012, 6:15 am

All times are UTC [ DST ]




Post new topic Reply to topic  [ 52 posts ]  Go to page Previous  1, 2, 3, 4
Author Message
 Post subject:
PostPosted: May 23rd, 2007, 12:08 pm 
Offline

Joined: May 24th, 2006, 2:49 pm
Posts: 4511
Location: Belgrade
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.

_________________
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 23rd, 2007, 1:55 pm 
Offline

Joined: April 21st, 2007, 9:16 pm
Posts: 178
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


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 23rd, 2007, 10:14 pm 
Offline

Joined: April 21st, 2007, 9:16 pm
Posts: 178
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


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 24th, 2007, 12:41 am 
Offline

Joined: May 24th, 2006, 2:49 pm
Posts: 4511
Location: Belgrade
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/35 ... r_moth.jpg

_________________
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 24th, 2007, 8:48 am 
Offline

Joined: April 21st, 2007, 9:16 pm
Posts: 178
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


Report this post
Top
 Profile  
Reply with quote  
PostPosted: May 24th, 2007, 11:46 am 
Offline

Joined: April 21st, 2007, 9:16 pm
Posts: 178
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


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 9th, 2011, 6:01 pm 
Offline

Joined: January 29th, 2009, 9:50 pm
Posts: 483
Location: Belgium
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
the code i post falls under the: WTFYW-WTFPL license


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 52 posts ]  Go to page Previous  1, 2, 3, 4

All times are UTC [ DST ]


Who is online

Users browsing this forum: 0x150||ISO, BobKnepper, Cerberus, just me, LazyMan, poserpro and 72 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group