2012-02-13 12 views
11

Come posso ottenere l'elenco di cartelle aperte, enumerarle e minimizzare ogni cartella a livello di codice?Come minimizzare a livello di programmazione le cartelle di finestre aperte

A volte alcune cartelle aperte rubano lo stato attivo dallo strumento quando si passa da un modulo dell'applicazione a un altro. Prevenire questo è di alta priorità per il nostro cliente. I clienti sono persone ipovedenti, quindi accedono alla macchina solo tramite screen reader. Minimizzare altre finestre (cartelle) non è affatto un problema, anzi un requisito.

ho provato questo:

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

Come previsto ha fatto nulla di buono.

Aggiornamento:

Dalle risposte qui, ho provato questo:

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); 
    } 

Questo crea un sacco di finestre explorer invisibili ad essere improvvisamente elencati nel taksbar dal nulla. Sono poco abituato a gestire le API di Windows, quindi il codice stesso sarà di grande aiuto.

+0

È necessario inviare un messaggio alla finestra, questo deve essere fatto a livello di API di Windows. – Arjang

+0

@Arjang posso vedere qualche codice da qualche parte? – nawfal

+1

Se avessi il codice, sarebbe stata una risposta, non un commento. Volevo solo essere di aiuto in una ricerca di google migliore. – Arjang

risposta

3

C'è una soluzione meno 'hacky' che la risposta accettata disponibile qui: Minimize a folder

Si basa sul Shell Objects for Scripting.Esempio:

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); 
} 

La stessa cosa può essere realizzato utilizzando il 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); 
} 
+0

Simon, grazie per quello, funziona. Inoltre, invece di 'new Shell(). Windows' puoi chiamare' new ShellWindows() 'in' interop.SHDocVw'. Un vantaggio della risposta accettata è che è facile da estendere anche alle finestre di altre applicazioni, ma ciò è più semplice per l'attività specificata. Sono in due menti su quale risposta accettare :) – nawfal

+0

Posso aggiungere un piccolo snippet di codice alla tua risposta per dimostrare? Anche questo ha un * piccolo * problema in cui distoglie l'attenzione dall'app. Non che sia difficile da riportare, ma è comunque un piccolo problema. Ti capita? E sai perché sarebbe successo? – nawfal

+0

@nawfal: puoi aggiungere uno snippet se lo desideri. È vero che questo è legato solo alle finestre di Windows Explorer - questa era la domanda :-) e penso che sia molto più a prova di futuro. Se non vuoi minimizzare, usa semplicemente un altro comando ShowWindow, probabilmente SW_SHOWMINNOACTIVE. –

3

Se si desidera utilizzare p-invoke è possibile utilizzare EnumThreadWindows per enumerare tutte le finestre di un processo. Quindi utilizzare ShowWindow per ridurli al minimo.

+0

Grazie. Provami che – nawfal

+0

E 'questo per enumerare attraverso tutte le finestre generali? o solo finestre di cartelle? – nawfal

+0

È possibile enumerare tutte le finestre più in alto di un processo specifico utilizzando questo metodo. Nel tuo caso tutte le finestre che appartengono all'esploratore. È necessario ottenere un handle per il thread principale del processo. – rasmus

5

// Crea istanza di Shell di classe facendo riferimento COM Library "Controlli Microsoft Shell e Automazione" -shell32.dll

Shell32.ShellClass objShell = new Shell32.ShellClass(); 
//Show Desktop 
((Shell32.IShellDispatch4)objShell).ToggleDesktop(); 

Edit: per mostrare la vostra applicazione (Attivare o Ingrandisci/Ripristina) dopo la commutazione in realtà si è rivelata molto difficile:

ho provato:

Application.DoEvents(); 

System.Threading.Thread.Sleep(5000); 

Anche sovrascrivendo il WndProc non è riuscito a catturare l'evento:

private const Int32 WM_SYSCOMMAND = 0x112; 
     private const Int32 SC_MINIMIZE = 0xf020; 
     protected override void WndProc(ref Message m) 
     { 
      if (m.Msg == WM_SYSCOMMAND) 
      { 
       if (m.WParam.ToInt32() == SC_MINIMIZE) 
        return; 
      } 
      base.WndProc(ref m); 
     } 

Quindi suggerisco invece di minimizzare tutte le altre finestre, basta attaccare il vostro in alto durante l'operazione, quindi una volta che il finito spegnere Sempre in primo piano:

[DllImport("user32.dll")] 
    static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags); 

static readonly IntPtr HWND_TOPMOST = new IntPtr(-1); 

const UInt32 SWP_NOSIZE = 0x0001; 
const UInt32 SWP_NOMOVE = 0x0002; 
const UInt32 TOPMOST_FLAGS = SWP_NOMOVE | SWP_NOSIZE; 

public static void MakeTopMost (IntPtr hWnd) 
{ 
    SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, TOPMOST_FLAGS); 
} 
+0

Questo minimizza tutto, compresa la mia app. this.Attivate non lo porta in primo piano – nawfal

+0

scusa dovrebbe essere this.WindowState = FormWindowState.Maximized; –

+0

In nessun modo. mantiene ancora il mio modulo in basso :( – nawfal

8

si prega di provare questo (il codice è un po 'disordinato, ma per lo scopo si dovrebbe essere in grado di passare attraverso di essa;))

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Windows.Forms; 
using System.Runtime.InteropServices; 
using System.Diagnostics; 
using System.Text; 
using System.Globalization; 

namespace WindowsFormsApplication20 
{ 
    static class Program 
    { 
     [STAThread] 
     static void Main() 
     { 
      foreach (IntPtr handle in EnumerateProcessWindowHandles(Process.GetProcessesByName("explorer")[0].Id)) 
      { 
       SendMessage(handle, WM_SYSCOMMAND, SC_MINIMIZE, 0); 
      } 
     } 

     [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] 
     static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount); 

     static string GetDaClassName(IntPtr hWnd) 
     { 
      int nRet; 
      StringBuilder ClassName = new StringBuilder(100); 
      //Get the window class name 
      nRet = GetClassName(hWnd, ClassName, ClassName.Capacity); 
      if (nRet != 0) 
      { 
       return ClassName.ToString(); 
      } 
      else 
      { 
       return null; 
      } 
     } 

     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) 
      { 
       string className = GetDaClassName(hWnd); 

       switch (className) 
       { 
        case null: 
         break; 
        case "ExploreWClass": 
         handles.Add(hWnd); 
         break; 
        case "CabinetWClass": 
         handles.Add(hWnd); 
         break; 
        default: 
         break; 
       } 

       return true; 
      }; 

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

      return handles; 
     } 

     [DllImport("user32.dll", CharSet = CharSet.Auto)] 
     static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, int wParam, int lParam); 

     const int WM_SYSCOMMAND = 274; 
     const int SC_MINIMIZE = 0xF020; 
    } 
} 

con i migliori saluti,

01.235.

Żubrówka

+0

Fammi provare quello! Grazie :) – nawfal

+0

I non posso credere, ha funzionato! :) – nawfal

+0

Prima di assegnarti la taglia, lascia che ti chieda, cosa dovrebbe essere fatto per minimizzare altre finestre aperte, diciamo tutte le finestre MS Excel (usando la stessa API della shell? – nawfal

0

So che questo è un vecchio post, ma qui è un modo molto più breve, più semplice nel caso in cui le persone sono ancora alla ricerca di un soluzione:

Utilizzando le API di Windows:

Dichiarare una maniglia di Windows: (minimizza l'eseguibile chiamante)

HWND wHandle; //can be any scope - I use it in main 

chiamare il seguente ovunque (a seconda del campo di applicazione wHandle):

wHandle = GetActiveWindow(); 
ShowWindow(wHandle, SW_SHOWMINNOACTIVE); 
Problemi correlati