C# 界面检测显示器移除并在可用显示器上显示

C# 检测显示器被移除,将界面在当前可用的显示器上显示,避免程序在任务栏点击无响应。

cs 复制代码
using System;
using System.Linq;
using System.Windows.Forms;

public class MonitorWatcher : IDisposable
{
    private readonly Form _targetForm;
    private Screen _currentScreen;
    private bool _disposed = false;

    public MonitorWatcher(Form form)
    {
        _targetForm = form ?? throw new ArgumentNullException(nameof(form));
        _currentScreen = GetCurrentScreen();
        
        // 订阅显示器变化事件
        SystemEvents.DisplaySettingsChanged += OnDisplaySettingsChanged;
    }

    private Screen GetCurrentScreen()
    {
        if (!_targetForm.IsHandleCreated || _targetForm.WindowState == FormWindowState.Minimized)
        {
            return Screen.PrimaryScreen;
        }
        
        return Screen.FromHandle(_targetForm.Handle);
    }

    private void OnDisplaySettingsChanged(object sender, EventArgs e)
    {
        // 检查当前显示器是否仍然存在
        var allScreens = Screen.AllScreens;
        bool currentScreenExists = allScreens.Any(s => s.DeviceName == _currentScreen.DeviceName);

        if (!currentScreenExists)
        {
            // 当前显示器已移除,迁移到其他显示器
            MoveToAvailableScreen();
        }
        
        // 更新当前显示器信息
        _currentScreen = GetCurrentScreen();
    }

    private void MoveToAvailableScreen()
    {
        var availableScreens = Screen.AllScreens;
        if (availableScreens.Length == 0)
        {
            return; // 没有可用显示器
        }

        // 选择最合适的显示器(优先主显示器)
        var targetScreen = availableScreens.FirstOrDefault(s => s.Primary) ?? availableScreens[0];

        // 计算新位置,确保窗口完全可见
        var newLocation = CalculateNewPosition(_targetForm, targetScreen);
        
        // 移动窗口
        _targetForm.Location = newLocation;
        
        // 如果窗口最大化,先恢复再移动再最大化
        if (_targetForm.WindowState == FormWindowState.Maximized)
        {
            _targetForm.WindowState = FormWindowState.Normal;
            _targetForm.Location = newLocation;
            _targetForm.WindowState = FormWindowState.Maximized;
        }
    }

    private Point CalculateNewPosition(Form form, Screen screen)
    {
        // 确保窗口完全在目标显示器的工作区域内
        Rectangle workingArea = screen.WorkingArea;
        int newX = workingArea.Left;
        int newY = workingArea.Top;
        
        // 如果窗口大小超过工作区,调整大小
        if (form.Width > workingArea.Width)
        {
            form.Width = workingArea.Width;
        }
        if (form.Height > workingArea.Height)
        {
            form.Height = workingArea.Height;
        }
        
        return new Point(newX, newY);
    }

    public void Dispose()
    {
        if (!_disposed)
        {
            SystemEvents.DisplaySettingsChanged -= OnDisplaySettingsChanged;
            _disposed = true;
        }
    }
}

调用例子方法

cs 复制代码
using System;
using System.Windows.Forms;

public partial class MainForm : Form
{
    private MonitorWatcher _monitorWatcher;

    public MainForm()
    {
        InitializeComponent();
        
        // 初始化显示器监控
        _monitorWatcher = new MonitorWatcher(this);
        
        // 窗体关闭时释放资源
        this.FormClosed += (s, e) => _monitorWatcher.Dispose();
    }
}

如果遇到没有定义的类,使用右键"快速操作和重构..." vs会弹出解决方法,选择弹出的解决方式。

相关推荐
集芯微电科技有限公司17 天前
四通道2A输出集成功率电感降压模块专为紧凑型方案设计
人工智能·单片机·嵌入式硬件·生成对抗网络·计算机外设
lichong95117 天前
让AI自己用电脑!Cua:后台操作鼠标键盘,Mac/Windows/Linux全支持
人工智能·macos·ai·计算机外设·agent·提示词
Saniffer_SH18 天前
【高清视频】Gen6 服务器还没到,Gen6 SSD 怎么测?Emily 现场演示三种测试环境
人工智能·驱动开发·测试工具·缓存·fpga开发·计算机外设·压力测试
阿泽·黑核18 天前
05 keyflow 扩展设计方案:矩阵键盘/组合键/事件队列/中断驱动
线性代数·矩阵·计算机外设·嵌入式·agent·vibe coding
科技每日热闻18 天前
618 AI显示器选购指南!爱攻AGON AI定制芯片电竞显示器AG277UX,适合哪些玩家?
人工智能·科技·游戏·计算机外设
科技每日热闻18 天前
舒视蓝4.0 AI版!EVNIA弈威海王星系列护眼电竞显示器27M4P5501U来袭
人工智能·科技·游戏·计算机外设
开开心心_Every19 天前
界面干净的开源免费电视浏览器
人工智能·科技·智能手机·计算机外设·rabbitmq·语音识别·etcd
智塑未来21 天前
2026高性价比商用护眼显示器调研:飞利浦护眼技术与售后体系深度解析
计算机外设
移远通信21 天前
显示器-调试
单片机·嵌入式硬件·计算机外设
Legendary_00821 天前
LDR6020P:iPad 一体式皮套键盘 OTG 应用的核心引擎
ios·计算机外设·ipad