How to Find the Handle of the TopMost Window

Last reviewed: June 21, 1995
Article ID: Q126386
The information in this article applies to:

- Standard and Professional Editions of Microsoft Visual Basic for

  Windows, versions 2.0 and 3.0

SUMMARY

There can be many TopMost windows in the Z-Order. TopMost windows are those that have their WS_EX_TOPMOST Windows style set. This article describes how to find the handle of the Window that occupies the top-most position above all other windows -- that is, the top-most TopMost window. This is the window that has the highest Z-Order in Windows internal Window Manager List.

MORE INFORMATION

Given the window handle of the startup form or any other non-child form, you can use the GetWindow API function to find the very first window (highest Z-Order) in the Window Manager List. This window need not neccessarily be the top-most visible window on the screen. However, if the SetActiveWindow API function is called immediately after, the next visible Top-most window (the one that is actually visible as the topmost Window on the screen) will be Activated. Then you can use the GetActiveWindow API function to get the window handle of the top-most visible Window on the screen.

Step-by-Step Example

  1. Start a new project in Visual Basic. Form1 is created by default.

  2. Create a new form (Form2), and add it to the project.

  3. Create a new Code Module and add the following statements:

       'Enter each Declare statement as one, single line:
       Declare Function GetActiveWindow Lib "User" () As Integer
       Declare Function GetWindow Lib "User"
          (ByVal hWnd As Integer, ByVal wCmd As Integer) As Integer
       Declare Function SetActiveWindow Lib "User"
          (ByVal hWnd As Integer) As Integer
       Global Const GW_HWNDFIRST = 0
       Global Const GW_HWNDNEXT = 2
    
    

  4. Place a Command Button (Command1) on Form1, and add the following code to its Click event:

       Sub Command1_Click ()
          Dim TopMosthWnd%, OldActivehWnd%, NewActivehWnd%
    
          TopMosthWnd% = GetWindow(Me.hWnd, GW_HWNDFIRST)
          OldActivehWnd% = SetActiveWindow(TopMosthWnd%)
          NewActivehWnd% = GetActiveWindow()
    
          ' The following code is required only if there is more than one
          ' non-child form in the project. In this case you will have to
          ' start from the next topmost window, if focus shifts to the
          ' other non-child forms, just before this code on the original
          ' form is executed.
    
          While NewActivehWnd% = 0
             TopMosthWnd% = GetWindow(TopMosthWnd%, GW_HWNDNEXT)
             OldActivehWnd% = SetActiveWindow(TopMosthWnd%)
             NewActivehWnd% = GetActiveWindow()
          Wend
       End Sub
    
    

  5. Add the following code to the Form_Load() Event of Form1:

       ' This is Optional. It is used to show the effect of another
       ' non-child form:
    
       Sub Form_Load ()
          form2.Show
       End Sub
    
    

  6. For testing purposes, before running the program, open any help window and choose the "always on top" option from the Help menu. In addition, you could do the same for the windows clock program by choosing the "always on top" option from the control menu.

  7. Press F5 to run the program. Click the command button. The focus will shift to the window currently positioned above all other windows.

NOTE: The code listed in this article will work even if it is executed from an MDI Parent associated event. To achieve the same results if executed from an event associated with a child (MDI or non-MDI) window, you will need to replace the following line of code at the beginning of the Sub procedure:

   TopMosthWnd% = GetWindow(Me.hWnd, GW_HWNDFIRST)

with these two lines of code:

   TopMosthWnd% = GetWindow(Me.hWnd, GW_OWNER)
   TopMosthWnd% = GetWindow(TopMosthWnd%, GW_HWNDFIRST)

and include the following line in the code module:

   Global Const GW_OWNER = 4


Additional reference words: 3.00
KBCategory: kbprg kbcode
KBSubCategory: APrgWindow


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: June 21, 1995
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.