在 C# 中使用 SetWindowPos 来移动窗口

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1190423/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 10:26:03  来源:igfitidea点击:

Using SetWindowPos in C# to move windows around

c#windowsinterop

提问by Matt

I have the code below:

我有下面的代码:

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

This is supposed to move every window on my desktop to 0,0 (x,y) and keep the same sizes. My problem is that only the calling app (built in C#) is getting moved.

这应该将我桌面上的每个窗口移动到 0,0 (x,y) 并保持相同的大小。我的问题是只有调用应用程序(内置在 C# 中)被移动。

Should I be using something else other than Control.FromHandle(IntPtr)? Will this only find dotnet controls? If so what should I use?

我应该使用 Control.FromHandle(IntPtr) 以外的其他东西吗?这只会找到 dotnet 控件吗?如果是这样,我应该使用什么?

Also, the second 0 in SetWindowPos was just a random int I stick in there, I'm not sure what to use for int hWndInsertAfter

此外,SetWindowPos 中的第二个 0 只是我坚持在那里的一个随机 int,我不确定用于 int hWndInsertAfter

What about processes with multiple windows like pidgin?

像 pidgin 这样具有多个窗口的进程呢?

采纳答案by Reed Copsey

Just take out your Control.FromHandle and the form == null check. You should be able to just do:

只需取出您的 Control.FromHandle 和 form == null 检查。你应该能够做到:

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

If you add SWP_NOSIZE, it will not resize the window, but will still reposition it.

如果添加 SWP_NOSIZE,它不会调整窗口大小,但仍会重新定位它。

If you want to effect all windows, not just the main window, of each process, you might want to consider using P/Invoke withEnumWindowsinstead of iterating through the Process list and using MainWindowHandle.

如果您想影响每个进程的所有窗口,而不仅仅是主窗口,您可能需要考虑将P/Invoke 与EnumWindows一起使用而不是遍历进程列表并使用 MainWindowHandle。

回答by Dagne

Played with this. See if it helps.

玩过这个。看看它是否有帮助。



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