Search code examples
c#processcomboboxbringtofront

Activating Form By Title Throws System.NullReferenceException


so I have a form with a ComboBox that I populate with a list of open processes (In this case, I limit it to processes with titles that have 13 characters.) When I select an Item in the ComboBox I want to find that Form by Title and BringToFront However when I do so, it throws a System.NullReferenceException.

Here's the code I use to populate the box.

using HWND = IntPtr;
public static class OpenWindowGetter
{
    /// <summary>Returns a dictionary that contains the handle and title of all the open windows.</summary>
    /// <returns>A dictionary that contains the handle and title of all the open windows.</returns>
    public static IDictionary<HWND, string> GetOpenWindows()
    {
        HWND shellWindow = GetShellWindow();
        Dictionary<HWND, string> windows = new Dictionary<HWND, string>();

        EnumWindows(delegate (HWND hWnd, int lParam)
        {
            if (hWnd == shellWindow) return true;
            if (!IsWindowVisible(hWnd)) return true;

            int length = GetWindowTextLength(hWnd);
            if (length == 0) return true;

            StringBuilder builder = new StringBuilder(length);
            GetWindowText(hWnd, builder, length + 1);

            windows[hWnd] = builder.ToString();
            return true;

        }, 0);

        return windows;
    }

    private delegate bool EnumWindowsProc(HWND hWnd, int lParam);

    [DllImport("USER32.DLL")]
    private static extern bool EnumWindows(EnumWindowsProc enumFunc, int lParam);

    [DllImport("USER32.DLL")]
    private static extern int GetWindowText(HWND hWnd, StringBuilder lpString, int nMaxCount);

    [DllImport("USER32.DLL")]
    private static extern int GetWindowTextLength(HWND hWnd);

    [DllImport("USER32.DLL")]
    private static extern bool IsWindowVisible(HWND hWnd);

    [DllImport("USER32.DLL")]
    private static extern IntPtr GetShellWindow();
}

public void populateIncidents()
    {
        foreach (KeyValuePair<IntPtr, string> window in OpenWindowGetter.GetOpenWindows())
        {
            IntPtr handle = window.Key;
            string title = window.Value;
            if (title.Length == 13)
            {
                chooseIncidentBox.Items.Add(title);
            }
        }
    }

And here's the code I'm using to try to show the Form.

private void chooseIncidentBox_SelectedIndexChanged(object sender, EventArgs e)
    {
        sSelectedIncident = chooseIncidentBox.Text;
        Application.OpenForms[sSelectedIncident].BringToFront(); //Exception thrown here.
    }

I'm not quite sure why it's throwing the exception, I know the Form exists as it wouldn't populate the ComboBox otherwise. Any help would be greatly appreciated.


Solution

  • The code you have gives all the active windows. Now, Application.OpenForms works only on the forms which are opened in your application. For example, if you have ParentForm and ChildFormin your application and both are open, OpenForms collection will contain these two.

    What you are looking for is to bring any process window in front. You can make use of SetForegroundWindow in User32.dll to do so. This SO question looks fairly similar to what you need. Take a look at the accepted solution.