2009-07-27 25 views
19

Ho il codice qui sotto:Uso SetWindowPos in C# per spostare le finestre

namespace WindowMover 
{ 
    using System.Windows.Forms; 

    static class Logic 
    { 
     [DllImport("user32.dll", EntryPoint = "SetWindowPos")] 
     public static extern IntPtr SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int Y, int cx, int cy, int wFlags); 

     public static void Move() 
     { 
      const short SWP_NOMOVE = 0X2; 
      const short SWP_NOSIZE = 1; 
      const short SWP_NOZORDER = 0X4; 
      const int SWP_SHOWWINDOW = 0x0040; 

      Process[] processes = Process.GetProcesses("."); 
      foreach (var process in processes) 
      { 
       var handle = process.MainWindowHandle; 
       var form = Control.FromHandle(handle); 

       if (form == null) continue; 

       SetWindowPos(handle, 0, 0, 0, form.Bounds.Width, form.Bounds.Height, SWP_NOZORDER | SWP_SHOWWINDOW); 
      } 
     } 
    } 
} 

Questo dovrebbe spostare ogni finestra sul mio desktop a 0,0 (x, y) e mantenere le stesse dimensioni. Il mio problema è che solo l'app chiamante (costruita in C#) viene spostata.

Devo usare qualcos'altro oltre a Control.FromHandle (IntPtr)? Questo troverà solo controlli dotnet? Se sì, cosa dovrei usare?

Inoltre, il secondo 0 a SetWindowPos era solo un int a caso mi attengo in là, io non sono sicuro di cosa usare per int hWndInsertAfter

Che dire di processi con più finestre come pidgin?

risposta

23

Basta estrarre il Control.FromHandle e il modulo == controllo null. Si dovrebbe essere in grado di fare solo:

IntPtr handle = process.MainWindowHandle; 
if (handle != IntPtr.Zero) 
{ 
    SetWindowPos(handle, 0, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW); 
} 

Se si aggiunge SWP_NOSIZE, non sarà ridimensionare la finestra, ma sarà ancora riposizionarla.

Se si desidera effettuare tutte le finestre, non solo la finestra principale, di ogni processo, si potrebbe desiderare di considerare l'utilizzo di P/Invoke withEnumWindows invece che scorrendo l'elenco dei processi e l'utilizzo di MainWindowHandle.

+0

Si sta facendo lì, ma alcune finestre (sembra come quei processi che hanno più finestre) non sono tutti in movimento. BTW, rispondi a molte delle mie domande, spero di avere un po 'di know-how di programmazione .... – Matt

+0

Matt: Ho aggiunto la soluzione per questo: non ho visto quella risposta fino alla fine. EnumWindows itererà attraverso tutte le finestre di livello superiore (non solo le finestre MainWindowHandle), che dovrebbero darti quello che vuoi. –

2

Giocato con questo. Vedi se aiuta.


using System.Windows.Forms; 
using System.Runtime.InteropServices; 
using System.Diagnostics; 


namespace ConsoleTestApp 
{ 
class Program 
{ 
    [DllImport("user32.dll")] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    static extern bool SetForegroundWindow(IntPtr hWnd); 

    static void Main(string[] args) 
    { 

     Process[] processes = Process.GetProcesses(); 

     foreach (var process in processes) 
     { 
      Console.WriteLine("Process Name: {0} ", process.ProcessName); 

      if (process.ProcessName == "WINWORD") 
      { 
       IntPtr handle = process.MainWindowHandle; 

       bool topMost = SetForegroundWindow(handle); 
      } 
     } 
} 
} 

Problemi correlati