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

WinForm多屏幕选择器按钮布局匹配系统配置问题求助

WinForm屏幕选择按钮布局不匹配系统配置

在Windows 11家庭版环境下,使用C# WinForm(.NET 8.0)开发一款支持物理屏幕选择的App Launcher,当前无法实现与系统屏幕布局一致的按钮排布:期望按钮分布匹配实际屏幕配置,但实际效果不符。

未解决问题

  • 按钮顺序错误
  • 按钮布局无法匹配系统配置

当前最接近预期的代码

using System.Runtime.InteropServices;

namespace WebStack_Deployer_for_Docker.Forms
{
    public partial class DisplaySelector : Form
    {
        private const int SW_SHOWNORMAL = 1;

        [StructLayout(LayoutKind.Sequential)]
        private struct POINT
        {
            public int X;
            public int Y;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct RECT
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct WINDOWPLACEMENT
        {
            public int length;
            public int flags;
            public int showCmd;
            public POINT ptMinPosition;
            public POINT ptMaxPosition;
            public RECT rcNormalPosition;
        }

        public readonly int screens = Screen.AllScreens.Length;

        private Panel panelMonitors;

        private const int ButtonWidth = 160;

        private const int ButtonHeight = 100;

        public DisplaySelector()
        {
            InitializeComponent();
            InitializeMonitorSelection();
        }

        private void InitializeMonitorSelection()
        {
            panelMonitors = new Panel
            {
                Dock = DockStyle.Fill
            };
            Controls.Add(panelMonitors);

            Screen[] allScreens = Screen.AllScreens;
            Array.Sort(allScreens, (a, b) => a.Bounds.X.CompareTo(b.Bounds.X));

            int totalScreens = allScreens.Length;

            int startX = (ClientSize.Width - totalScreens * (ButtonWidth + 20)) / 2;
            int startY = (ClientSize.Height - ButtonHeight) / 2;

            for (int i = 0; i < totalScreens; i++)
            {
                int monitorIndex = i;
                Button monitorButton = new Button
                {
                    Text = $"Pantalla #{monitorIndex + 1}",
                    Tag = monitorIndex,
                    Size = new Size(ButtonWidth, ButtonHeight),
                    // Calcula la posición X y Y del botón de acuerdo a la disposición real de las pantallas
                    Location = CalculateButtonPosition(startX, startY, monitorIndex, totalScreens, ButtonWidth)
                };

                monitorButton.Click += MonitorButton_Click;
                panelMonitors.Controls.Add(monitorButton);
            }
        }

        private Point CalculateButtonPosition(int startX, int startY, int monitorIndex, int totalScreens, int buttonWidth)
        {

            int positionX = startX;
            if (monitorIndex > 0)
            {
                positionX += (buttonWidth + 20) * monitorIndex;
            }

            int positionY = startY;

            if (totalScreens > 1)
            {
                if (monitorIndex == 0)
                {
                    positionY -= ButtonHeight / 2 + 20;
                }
                else if (monitorIndex == totalScreens - 1)
                {
                    positionY += ButtonHeight / 2 + 20;
                }
            }

            return new Point(positionX, positionY);
        }

        private void MonitorButton_Click(object sender, EventArgs e)
        {
            Button clickedButton = (Button)sender;
            int monitorIndex = (int)clickedButton.Tag;
            MessageBox.Show($"Has seleccionado el Monitor #{monitorIndex}");
            MoveToDisplay(monitorIndex);
        }

        public static void MoveToDisplay(int display)
        {
            if (Screen.AllScreens.Length > 1)
            {
                IntPtr windowHandle = GetForegroundWindow();

                WINDOWPLACEMENT placement = new WINDOWPLACEMENT
                {
                    length = Marshal.SizeOf(typeof(WINDOWPLACEMENT))
                };
                GetWindowPlacement(windowHandle, ref placement);

                Rectangle secondMonitor = Screen.AllScreens[display].WorkingArea;
                int windowWidth = placement.rcNormalPosition.Right - placement.rcNormalPosition.Left;
                int windowHeight = placement.rcNormalPosition.Bottom - placement.rcNormalPosition.Top;
                int windowLeft = secondMonitor.Left + (secondMonitor.Width - windowWidth) / 2;
                int windowTop = secondMonitor.Top + (secondMonitor.Height - windowHeight) / 2;

                placement.rcNormalPosition.Left = windowLeft;
                placement.rcNormalPosition.Top = windowTop;
                placement.rcNormalPosition.Right = windowLeft + windowWidth;
                placement.rcNormalPosition.Bottom = windowTop + windowHeight;
                placement.showCmd = SW_SHOWNORMAL;

                SetWindowPlacement(windowHandle, ref placement);
            }
        }

        [DllImport("user32.dll")]
        private static extern IntPtr GetForegroundWindow();

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool GetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool SetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 17:05:03