PlanetSquires Forums

Support Forums => Other Software and Code => Topic started by: Roger Garstang on June 20, 2004, 05:37:29 PM

Title: Trayicon Question
Post by: Roger Garstang on June 20, 2004, 05:37:29 PM
Not sure how many other people use tray icons, but I've got an interesting thing I want to do with my tray icon menu.  On right clicking it I bring up the menu using TrackPopupMenu as pretty much everyone does, and of course before calling this thanks to Microsloth's "Design" we have to call SetForegroundWindow otherwise the menu doesn't work properly.

This creates the side effect of if the window is open and underneath the app the user is working with then right clicking plops the window right on top of what they are doing.  If the window is hidden it works fine and doesn't interupt them.  I've tried using SetActiveWindow which is supposed to be the milder form that doesn't put the window in front of them, but this doesn't work.  Is there another API call that I can't think of to do this?  Apps like Yahoo IM and the network status lights can right click without bringing the window in front while some other Apps like ZoneAlarm, etc bring it in front as mine does...all of the menus work though, and all of the windows are getting an Activate message.

Only thing I can figure is Yahoo IM and the Status Lights use some hidden window to handle the messages, but that wouldn't explain why the main app still gets the Activate message???
Title: Trayicon Question
Post by: Roger Garstang on June 23, 2004, 07:45:05 AM
Update:

I've made some progress so far...not much, but:

SendMessage(HWND, %WM_SETREDRAW, %FALSE, 0)

is somewhat usefull when called before Setting it foreground, then moving the window to the bottom of the Z-Order and turning %WM_SETREDRAW back on with %TRUE, etc...but creates some screen update problems. (Mostly with other apps leaving a ghost image, while mine starts painting again...go figure)

I also found out that trying to get the current Active/Top/Foreground window doesn't work well.  Active Window works, but only can tell you if your thread's window is active, and the others don't work at all because when you click your app's tray icon either your app or the tray window are considered the Top/ForeGround window and not what you were just working with.

I could most likely use the mouse moving over the icon to grab the current Foreground window to a static variable and use it to return back to that window after the menu selection is finished, but Win2K/XP allow selecting the icon with the keyboard which doesn't produce any message then if they select the Context Menu key the value will be wrong.  :?

Leave it to Microsoft to make a design that can almost be rigged to work...but then they change it so it can't be.  Only other option is to make the NOTIFYICONDATA structure the new type that isn't declared in PB's inc files and maybe specify for it to use the Win95 features, but I'd then have to do version checking and I would assume using the old NOTIFYICONDATA structure and size would already use the Win95 version...but the icon can still get focus with the keyboard, so I guess not.

There is just something about the window being visible that makes the problems too.  Just using SetFocus or setting the Active Window without making it the ForeGround Window work fine when it is hidden.  Another side effect of Setting it to ForeGround when hidden is keypresses are sent to an invisible window.  Microsoft Really Screwed up with this thing needing to be ForeGround.

Maybe I'll just subclass the tray and show them how to make it work correctly.  :twisted:
Title: Trayicon Question
Post by: Haakon Birkeland on June 23, 2004, 08:04:31 AM
Sometimes I'm puzzled over how complicated apparently 'easy' things have to be when done the Ms-way. Kind of reminds me of those darn MCP tests I took some years back. We had the theoretical way, the practical way, and the way Ms said it did work. Which apparently where neither the theoretical nor the practical it actually workedt.. 75 multiple choice questions in 45 minutes, - puh..  :twisted:
Title: Trayicon Question
Post by: Roger Garstang on June 23, 2004, 08:12:54 AM
Yeah, I feel like just contacting Yahoo and AOL and asking how they get their menus to popup without making the window foreground, but if they spent as long as I have on something so stupid they'd probably laugh and tell me to figure it out myself like they had to.  I've wore out Winspector trying to figure it out.  There window still gets the same Activate messages, etc...only thing different I notice is mine gets some EnterMenuLoop message or something.  Maybe they just aren't using standard menus?

I did find out one thing funny though while playing with all of this.  You can't see any of ZoneAlarm's messages!  The main app is loaded by the SYSTEM account so it can't be viewed, and the window that opens with the icon is some dummy window with a bunch of controls starting with the name Widget and receives no messages???
Title: Trayicon Question
Post by: Roger Garstang on June 23, 2004, 06:05:19 PM
I tried the code below to put the window back where it was, but it only seems to work the first time even though the values are local.


GetCursorPos Pt
isActive= GetFocus()
If isActive= 0 Then prevWindow= GetNextWindow(HWND, %GW_HWNDPREV)
SetForegroundWindow(HWND)
If isActive= 0 Then SetWindowPos(HWND, prevWindow, 0, 0, 0, 0, %SWP_NOSIZE Or %SWP_NOMOVE Or %SWP_NOACTIVATE)
TrackPopupMenu(trayMenu, %TPM_RIGHTALIGN Or %TPM_LEFTBUTTON Or %TPM_RIGHTBUTTON, Pt.x, Pt.y, 0, HWND, ByVal 0)
PostMessage(HWND, %WM_NULL, 0, 0)


:?  Changing %GW_HWNDPREV to %GW_HWNDNEXT works though.  Man this Z order stuff is confusing, they should have picked different names or something because I keep getting them backwards.


GetCursorPos Pt
prevWindow= GetNextWindow(HWND, %GW_HWNDNEXT)
SetForegroundWindow(HWND)
SetWindowPos(HWND, prevWindow, 0, 0, 0, 0, %SWP_NOSIZE Or %SWP_NOMOVE Or %SWP_NOACTIVATE)
SetFocus(0) 'Block Keystrokes to Window
TrackPopupMenu(trayMenu, %TPM_RIGHTALIGN Or %TPM_LEFTBUTTON Or %TPM_RIGHTBUTTON, Pt.x, Pt.y, 0, HWND, ByVal 0)
PostMessage(HWND, %WM_NULL, 0, 0)