Determine TopMost Window on the Desktop

Hi All,
I have a tricky one (well, tricky for me) that I am having trouble finding a solution for.

Here is the problem;
I have a Form that is open and a Notify Icon. I want to be able to click the icon and have one of two things occur depending on the current state of the form.

If the form is the Top Most (i.e. on top of all other normalised or maximised Windows) I want to hide the form.

If the form is NOT the Top Most (i.e. behind another form) then I want to bring the form to the top.

You can determine the topmost form for the desktop using a couple of Windows API's as follows;

'GetForegroundWindow will get the handle of the Forground Window...
PublicDeclareFunction GetForegroundWindowLib"user32" ()As IntPtr

'GetDesktopWindow will get the handle for the Desktop...
PublicDeclareFunction GetDesktopWindowLib"user32" ()As IntPtr

'GetTopWindow returns a handle to the currently active child window of a window.
'The active child window is the one that has the focus, and it is usually at the
'top of all the other children in the Z-order. This function works even if the parent
'window is not active. If an error occurs or the window has no children, the Function
'instead returns 0.
PublicDeclareFunction GetTopWindowLib"user32" (ByVal hwndAs IntPtr)As IntPtr

The problem as I see it is that because you have clicked the notify icon to kick off this logic, these API's will return the wrong Handle.

Does anyone have any idea how to determine that the form is currently on top of all other windows, even though it is not active?

Regards,

Grant.

[3130 byte] By [GrantCarthew] at [2007-12-16]
# 1
I'm not entirely sure what you are after, however:

Form.TopMost returns a value indicating whether the form is top most.

DavidM.Kean at 2007-9-9 > top of Msdn Tech,Visual Basic,Visual Basic General...
# 2
Hi Grant,

It looks like you've found the right APIs to use. Have you considered caching the hWnd of the foreground window during the MouseMove event of the NotifyIcon? Since the mouse has to move over the icon before it gets clicked, this should get you the right window.

RyanCavanaughMS at 2007-9-9 > top of Msdn Tech,Visual Basic,Visual Basic General...
# 3
Hi David,

I may be misunderstanding the MSDN Library, but as far as I can see, Form.TopMost allows you to set the form as a TopMost form, or find out if the form is set as TopMost. It does not tell you if the form is set as Form.TopMost = False but is currently the selected form.

Thanks.

GrantCarthew at 2007-9-9 > top of Msdn Tech,Visual Basic,Visual Basic General...
# 4
Smart thinking Ryan,

I will try it out later when I have time and get back to the forum with the result.

Side question: A lot of the examples of API calls on the web use Integer as the type when working with handles. I have been using IntPtr. Which is more correct?

Regards.

GrantCarthew at 2007-9-9 > top of Msdn Tech,Visual Basic,Visual Basic General...
# 5
IntPtr is a better choice if you plan to support 64-bit OSes. The size of IntPtr will change if the size of a pointer on the OS changes (as it does on a 64-bit OS). The size of Integer is fixed at 32-bits in current versions of VB.
KrisLa_MS at 2007-9-9 > top of Msdn Tech,Visual Basic,Visual Basic General...
# 6

Thanks for the IntPtr answer KrisLa.

Ryan, you're a champ. Works like a treat.

I created a class level variable mTopWindowHandle and using the GetForegroundWindow API in the Mouse move event, I record the Top Most Window Handle.

Then on the click event simply compare the forms handle with the mTopWindowHandle and process accordingly.

Thanks again for the idea. Sometimes it's the simple concept that keeps slipping through your fingers.

Regards,

Grant.

GrantCarthew at 2007-9-9 > top of Msdn Tech,Visual Basic,Visual Basic General...