28 votes

Utilisation de SetWindowPos en C# pour déplacer des fenêtres

J'ai le code ci-dessous :

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

Il est censé déplacer toutes les fenêtres de mon bureau à 0,0 (x,y) et conserver les mêmes tailles. Mon problème est que seule l'application appelante (construite en C#) est déplacée.

Dois-je utiliser autre chose que Control.FromHandle(IntPtr) ? Est-ce que cela ne trouvera que les contrôles dotnet ? Je ne sais pas si c'est le cas, mais je ne sais pas si c'est le cas.

De plus, le second 0 dans SetWindowPos était juste un int aléatoire que j'ai collé là, je ne suis pas sûr de ce qu'il faut utiliser pour int hWndInsertAfter

Qu'en est-il des processus avec plusieurs fenêtres comme pidgin ?

31voto

Reed Copsey Points 315315

Il suffit d'enlever le Control.FromHandle et la vérification form == null. Vous devriez pouvoir vous contenter de faire :

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

Si vous ajoutez SWP_NOSIZE, la fenêtre ne sera pas redimensionnée, mais elle sera repositionnée.

Si vous souhaitez agir sur toutes les fenêtres, et pas seulement sur la fenêtre principale, de chaque processus, vous pouvez envisager d'utiliser l'option P/Invoke avec EnumWindows au lieu d'itérer dans la liste des processus et d'utiliser MainWindowHandle.

1voto

user335830 Points 1

Joué avec ceci. Voyez si cela vous aide.


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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X