tags:

views:

65

answers:

1

We have implemented some custom tooltip-drawing code that fires on Tick events of a timer. Whenever this event fires, we check to make sure our control is visible (this.Visible) and is the foreground window (GetForegroundWindow()).

The problem we are having involves "always on top" windows like Task Manager or Process Explorer (when the "always on top" option is enabled). Because these windows are always on top, sometimes our application is occluded/covered by such windows, but our tooltip still pops up and gets drawn on top of the top window.

I have tried to use the Form.TopMost property, but this is not acceptable because then, tooltips never appear if there is an "always on top" window anywhere. In this case, our application is even active, so we should be showing the tooltips.

How do I detect/determine whether there is an "always on top" window covering the area on my form where the mouse is hovering? I want to prevent the tooltip from showing "through" the window.

+2  A: 

It sounds like you're polling the mouse position with a timer, and then displaying a tooltip. That's the wrong way to go. What you should do is detect mouse-move messages. If you get mouse-move events telling you that the mouse is in a certain region, then set a timer, and if the mouse hasn't left that region by the time the timer fires, display the tooltip. (Incidentally, that's how native Windows tooltips work. See TrackMouseEvent.)

That solves your problem with always-on-top windows automatically because if part of your window is obscured by an always-on-top window, your form simply won't receive mouse-move events for that region, so you don't need to check whether the mouse is really there.

If you're set on using your current technique, then you can use the WindowFromPoint API function to determine what window is visible at any given point on the screen. Use that to determine whether your window is on top at the place you plan to display the tooltip. (The .Net Framework API map says the .Net equivalent to that API function is Form.GetChildAtPoint, but that only gives children of a .Net form, whereas you need to consider all top-level windows, including non-.Net windows.)

Rob Kennedy