设置程序显示屏幕位置

在多屏显示系统中经常需要设置程序界面显示的屏幕位置,之前也曾写过控制屏幕位置的功能,偶然再一次使用中发现功能失效了,查了一下原因,这里对解决方案做一个简单的记录,以备备忘。

1.问题 “窗口启动位置 (WindowStartupLocation) 冲突”

首先说第一条:由于在设计程序时,一般会在主界面程序做默认设置窗体显示位置为屏幕中心位置,即 设置窗口的 WindowStartupLocation 设置为 CenterScreen 或 CenterOwner,后续手动设置 Left 和 Top 会被覆盖,导致设置失效。

  • 解决方法
    在构造函数中设置 WindowStartupLocation
    public MainWindow()
    {
      InitializeComponent();
      this.WindowStartupLocation = WindowStartupLocation.Manual; // 必须先设置
      Loaded += MainWindow_Loaded;
    }
    

2. 窗口状态 (WindowState) 冲突 (WindowStartupLocation) 冲突”

同上面类似,如果窗口处于最大化状态 (WindowState = Maximized),手动设置 Left 和 Top 无效

  • 解决方法
    在构造函数中设置 WindowsState,强制将窗口状态设为 Normal
    public MainWindow()
    {
     InitializeComponent();
     this.WindowStartupLocation = WindowStartupLocation.Manual; // 必须先设置
     this.WindowState=WindowState.Normal;//必须设置
     Loaded += MainWindow_Loaded;
    }
    

3. DPI 缩放问题”

问题:不同屏幕的 DPI 缩放比例不同,导致坐标计算错误。

  • 解决方案:
    将 System.Windows.Forms 获取的物理像素坐标转换为 WPF 的逻辑坐标。
    在窗体显示位置设置方法中增加坐标转换
    private void setAppPostion()
    {
        // 获取所有屏幕
        Screen[] screens = Screen.AllScreens;
    
        // 假设要显示在第二个屏幕(索引从0开始)
        int targetScreenIndex = Int32.Parse(ConfigurationManager.AppSettings["screenIndex"]);
     
        if (targetScreenIndex < screens.Length)
        {
            // 必须设置为Manual,手动指定位置
            this.WindowStartupLocation = WindowStartupLocation.Manual;
            Screen targetScreen = screens[targetScreenIndex];
            //获取当前窗口缩放比例
            var source = PresentationSource.FromVisual(this);
            if (source != null)
            {
                Matrix transform = source.CompositionTarget.TransformFromDevice;
                double dipX = transform.M11;//水平缩放比例
                double dipY = transform.M22;//垂直缩放比例
                //将物理像素转换为逻辑单位
                this.Left = targetScreen.WorkingArea.Left / dipX;
                this.Top = targetScreen.WorkingArea.Top / dipY;
                //设置窗口大小为目标屏幕的工作区域尺寸
                this.Width = targetScreen.WorkingArea.Width;
                this.Height = targetScreen.WorkingArea.Height;
            }
        }
    }
    
posted @ 2025-03-07 10:20  丹心石  阅读(74)  评论(0)    收藏  举报