How can i get the topmost form?

Posted on 2009-04-20
Last Modified: 2012-05-06
I have a background worker process which runs in the background (obviously). If the operation fails, i need a messagebox to pop up as a modal dialog owned by the currently open window (so that it doesnt disappear behind other windows).

My experience tells me that the Form.ActiveForm property does not always return a value.

I need a more reliable way of estabishing which open form should be the owner for the dialog window.

All windows in the application are displayed as modal. So we have a "stack" of windows open at any given time, and i need to return the topmost window on this stack.

Alternatively - if i set the owner to the first window in the "stack", will that result in the dialog being displayed above all other child windows?
Question by:tfsln
    LVL 39

    Expert Comment

    First, let's answer the story about the owner window.

    without an owner window and .Show
    this will open the window with as owner window the desktop. That means that window can be hidden or placed at any level in the z-order by user interaction of focusing the windows.

    The underlying window that opened the form has nothing to do with the opened window (except that it can keep a handle to it for closing the window programmatically). If the "parent" window is closed, the opened window will remain.

    with an owner window and .Show(this)
    this will open the window with as owner the specified window. This will always keep the window higher in the z-order then the owner window, which effectively means that the child window will always be obfuscating parts of the parent window.

    The underlying window that opened the form can still be accessed by the user. However, when he moves it, the child window will remain visible. Closing the parent window will also close the child window.

    without an owner window and .ShowDialog
    this will open the window with as owner the desktop, you would think. But in fact, the CLR will designate the opening window as the parent. This is effectively the same as the following:

    with an owner window and .ShowDialog(this)
    this will open the window with a owner the specified window. The opening window, the parent, is not accessible anymore if the user tries to select it. Closing the parent window (by a timer or something) will close the child, but it is common practice to first close the model children.

    stacking windows with .Show and .Show(this)
    suppose you open a chain of windows with an owner window, and then the last one without an owner window. Now, as soon as you select any off the parent windows, this last window will be hidden behind all the other windows.

    stacking windows with  .Show(this)
    opening a chain of windows with an owner window and closing any of the parents (at any level) will always close all its descendant (lower in z-order) children.

    .ActiveForm and modal windows
    the active form is the form that receives user input. You can have a modal window, which will always be returned by ActiveForm because it is blocking the underlying windows, but when a user selects another application, ActiveForm will return null.

    .ActiveForm and non-modal windows
    If you have a chain of non-modal windows, .ActiveForm will show the window that actually has the focus. This is not necessarily the top window, because if the windows are owned, they may obscure the underlying windows, but they won't show as modal.

    and now on with your actual question... :)


    Author Comment

    Cheers for that... im not sure whether this question is covered, but what happens if you have one master window with a stack of child windows like this;

    Window2 (owned by window1 - modal)
    Window3 (owned by window2 - modal)

    (when i say modal, i mean opened using ShowDialog as opposed to show)

    In this situation, what happens if you open a new modal window from inside the Window1 with the owner as Window1?
    LVL 39

    Expert Comment

    You cannot, so that is not a problem. You can only open a new modal window from within the topmost modal window.

    Your main part of the question, determining the top window, appears not trivial at all. There's no property you can use and there's no simple way to calculate the z-order from one to another, not even if your loop through all visible forms.

    If there's one chain of opening windows with one root, and each of them have the owner property set, then it becomes quite easy:

    foreach (Form frm in Application.OpenForms)
                    if(frm.OwnedForms.Length == 0)
                        // do something with the topform

    however, if you use several .Show(this) from your main form, then you get a certain tree with several branches:

    frm1 -- window1
       new MyForm().show(frm1)  -- window2
           new MyForm().show(this) --- window3
        new MyForm().show(frm1) -- window4

    now the user can click on window3 or window4 to bring them to the top. Both of them do not have owned forms (i.e., have the highest z-order), but there relative position is not clear.

    To get the correct relative position, I think you need to do old-school Win32 API and send a GetWindowPos, which will also retrieve the z-order.
    LVL 39

    Expert Comment

    > You cannot, so that is not a problem.

    to be a bit clearer on that subject: in general, you cannot and should not. But there are "workarounds". But the following:

    Form frm1 = new SomeForm();
    Form frm2 = new SomeForm();

    will block execution until the first ShowModal finishes. So no two modal popups at the same time.

    Now, if you would do something through an asynchronous timer call for instance, or you would open a window in the form_load that is an instance of self, then you will find that it actually is possible. Until you manage to crash Visual Studio (what I just did by opening too many modal windows... after hitting Break, VS did not recover and without warning disappeared).


    Author Comment

    > Now, if you would do something through an asynchronous timer call for instance

    Thats exactly what is happening in my situation - but i would have a check to make sure that the window wasnt open already (by using the Application.OpenForms collection) and if it was then i would not attempt to open a new one.

    The issue comes when trying to establish what to pass as the 'owner' parameter of the ShowDialog() function to ensure that the form is displayed on top of the current active window... you may be right i may need to use some old school api calls...
    LVL 39

    Accepted Solution

    I've been puzzled by this for over an hour now. Normally I'm quite handy with these things. Though it is easy to get the top level window that has the focus, even if ActiveForm would return null, it is far from trivial to get the window that is on top of the (visible) z-order. This is for a large part due to the method in which Windows arranges the windows amongst each other (parent/child and owner/owning) and that in the parlor of Windows, the topmost window is the window with the focus, even if it doesn't have the focus...
     In other words, to find the top window (the one not obscured by others) that is not necessarily the input window, is daunting to say the least. Strange as it can get, there is a SetWindowPos which includes a value for the z-order, but it the opposite, GetWindowPos does not exist
     A quick way of dealing with this problem is apparently just using a loop through consecutive FindWindowEx calls.

    Author Comment

    Thats cool ive got all the information i require cheers

    Write Comment

    Please enter a first name

    Please enter a last name

    We will never share this with anyone.

    Featured Post

    6 Surprising Benefits of Threat Intelligence

    All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

    In my previous two articles we discussed Binary Serialization ( and XML Serialization ( In this article we will try to know more about SOAP (Simple Object Acces…
    This article is for Object-Oriented Programming (OOP) beginners. An Interface contains declarations of events, indexers, methods and/or properties. Any class which implements the Interface should provide the concrete implementation for each Inter…
    Migrating to Microsoft Office 365 is becoming increasingly popular for organizations both large and small. If you have made the leap to Microsoft’s cloud platform, you know that you will need to create a corporate email signature for your Office 365…
    In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…

    760 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    8 Experts available now in Live!

    Get 1:1 Help Now