Search code examples
c#winformswinapic#-2.0focus-stealing

How to programmatically minimize opened window folders


How can I get the list of opened of folders, enumerate through it and minimize each folder programmatically?

At times some opened folders do steal focus from the tool when jumping from one form in the application to another. Preventing this is of high priority for our client. The customers are visually impaired people, so they access the machine only via screen readers. Minimizing other windows (folders) is not at all a problem, in fact a requirement.

I tried this:

foreach (Process p in Process.GetProcessesByName("explorer"))
{
    p.StartInfo.WindowStyle = ProcessWindowStyle.Minimized;
}

As expected it did no good.

Update:

From the answers here, I tried this:

    delegate bool EnumThreadDelegate(IntPtr hWnd, IntPtr lParam);

    [DllImport("user32.dll")]
    static extern bool EnumThreadWindows(int dwThreadId, EnumThreadDelegate lpfn, IntPtr lParam);

    static IEnumerable<IntPtr> EnumerateProcessWindowHandles(int processID)
    {
        List<IntPtr> handles = new List<IntPtr>();

        EnumThreadDelegate addWindowHandle = delegate(IntPtr hWnd, IntPtr param)
        {
            handles.Add(hWnd);
            return true;
        };

        foreach (ProcessThread thread in Process.GetProcessById(processID).Threads)                              
            EnumThreadWindows(thread.Id, addWindowHandle, IntPtr.Zero);

        return handles;
    }

    const int SW_MINIMIZED = 6;

    [DllImport("user32.dll")]
    static extern int ShowWindow(IntPtr hWnd, int nCmdShow);

    private void button1_Click(object sender, EventArgs e)
    {
        foreach (IntPtr handle in EnumerateProcessWindowHandles(Process.GetProcessesByName("explorer")[0].Id))
            ShowWindow(handle, SW_MINIMIZED);
    }

This creates a whole lot of invisible explorer windows to be suddenly listed in the taksbar out of no where. I am bit noob in dealing with Windows API, so the code itself will actually help.


Solution

  • There is a less 'hacky' solution than the accepted answer available here: Minimize a folder

    It's based on the Shell Objects for Scripting. Sample:

    const int SW_SHOWMINNOACTIVE = 7;
    
    [DllImport("user32.dll")]
    static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
    
    static void MinimizeWindow(IntPtr handle)
    {
        ShowWindow(handle, SW_SHOWMINNOACTIVE);
    }
    
    //call it like:
    
    foreach (IWebBrowser2 window in new Shell().Windows())
    {
        if (window.Name == "Windows Explorer")
            MinimizeWindow((IntPtr)window.HWND);
    }
    

    The same thing can be achieved using the Internet Explorer Object Model

    // add a reference to "Microsoft Internet Controls" COM component
    // also add a 'using SHDocVw;'
    foreach (IWebBrowser2 window in new ShellWindows())
    {
        if (window.Name == "Windows Explorer")
            MinimizeWindow((IntPtr)window.HWND);
    }