You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将两个打开的窗口分置于左右两侧(类似Win+←/→效果)

实现窗口分屏到屏幕左右两侧

要实现打开窗口后自动分屏到左右(类似Win+←/→的效果),需要完成以下核心步骤:

  • 打开目标窗口后,等待窗口创建并获取其句柄
  • 获取屏幕工作区尺寸(排除任务栏等系统元素)
  • 调用Windows API将窗口定位到左/右半屏区域

以下是修改后的完整代码:

using System;
using System.Runtime.InteropServices;
using System.Threading;

namespace OpenWindows
{
    class Program
    {
        // 导入所需Windows API
        [DllImport("Shell32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        static extern IntPtr ShellExecute(IntPtr hwnd, string lpOperation, string lpFile, string lpParameters, string lpDirectory, int nShowCmd);

        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

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

        [DllImport("user32.dll")]
        static extern IntPtr MonitorFromWindow(IntPtr hwnd, uint dwFlags);

        [DllImport("user32.dll")]
        static extern bool GetMonitorInfo(IntPtr hMonitor, ref MONITORINFO lpmi);

        // 辅助结构体
        [StructLayout(LayoutKind.Sequential)]
        public struct RECT
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct MONITORINFO
        {
            public int cbSize;
            public RECT rcMonitor;
            public RECT rcWork;
            public uint dwFlags;
        }

        // 循环等待窗口创建并获取句柄(最多等待10秒)
        static IntPtr WaitForWindow(string windowTitle, int timeoutSeconds = 10)
        {
            IntPtr hwnd = IntPtr.Zero;
            int attempts = timeoutSeconds * 10;
            while (attempts > 0)
            {
                hwnd = FindWindow(null, windowTitle);
                if (hwnd != IntPtr.Zero)
                    break;
                Thread.Sleep(100);
                attempts--;
            }
            return hwnd;
        }

        // 将窗口定位到左半屏
        static void MoveWindowToLeftHalf(IntPtr hwnd)
        {
            var monitorInfo = GetMonitorWorkArea(hwnd);
            int screenWidth = monitorInfo.rcWork.Right - monitorInfo.rcWork.Left;
            int screenHeight = monitorInfo.rcWork.Bottom - monitorInfo.rcWork.Top;

            SetWindowPos(hwnd, IntPtr.Zero,
                monitorInfo.rcWork.Left, monitorInfo.rcWork.Top,
                screenWidth / 2, screenHeight,
                0x0040 | 0x0001); // SWP_SHOWWINDOW | SWP_NOZORDER
        }

        // 将窗口定位到右半屏
        static void MoveWindowToRightHalf(IntPtr hwnd)
        {
            var monitorInfo = GetMonitorWorkArea(hwnd);
            int screenWidth = monitorInfo.rcWork.Right - monitorInfo.rcWork.Left;
            int screenHeight = monitorInfo.rcWork.Bottom - monitorInfo.rcWork.Top;

            SetWindowPos(hwnd, IntPtr.Zero,
                monitorInfo.rcWork.Left + screenWidth / 2, monitorInfo.rcWork.Top,
                screenWidth / 2, screenHeight,
                0x0040 | 0x0001); // SWP_SHOWWINDOW | SWP_NOZORDER
        }

        // 获取窗口所在显示器的工作区信息(排除任务栏)
        static MONITORINFO GetMonitorWorkArea(IntPtr hwnd)
        {
            IntPtr monitor = MonitorFromWindow(hwnd, 0x00000002); // MONITOR_DEFAULTTONEAREST
            MONITORINFO monitorInfo = new MONITORINFO();
            monitorInfo.cbSize = Marshal.SizeOf(monitorInfo);
            GetMonitorInfo(monitor, ref monitorInfo);
            return monitorInfo;
        }

        static void Main(string[] args)
        {
            // 打开存储设置窗口
            ShellExecute(IntPtr.Zero, "open", "ms-settings:storagesense", "", null, 9);
            // 等待窗口加载并获取句柄(中文系统标题为"存储感知",其他语言需对应修改)
            IntPtr settingsHwnd = WaitForWindow("存储感知");
            if (settingsHwnd != IntPtr.Zero)
                MoveWindowToLeftHalf(settingsHwnd);

            // 打开Edge浏览器窗口
            ShellExecute(IntPtr.Zero, "open", "msedge.exe", "www.google.com", null, 9);
            // 等待窗口加载并获取句柄(中文系统标题为"Google - Microsoft Edge",其他语言需对应修改)
            IntPtr edgeHwnd = WaitForWindow("Google - Microsoft Edge");
            if (edgeHwnd != IntPtr.Zero)
                MoveWindowToRightHalf(edgeHwnd);
        }
    }
}

关键注意点:

  • 窗口标题匹配:WaitForWindow中的窗口标题需和当前系统语言对应,比如英文系统下存储设置窗口标题是"Storage Sense",Edge窗口标题是"Google - Microsoft Edge"。
  • 等待机制:添加Thread.Sleep循环等待窗口创建,避免因窗口未加载完成导致无法获取句柄。
  • 工作区适配:通过GetMonitorWorkArea获取显示器实际可用区域,确保窗口不会被任务栏遮挡。

内容的提问来源于stack exchange,提问作者afei

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 08:10:31