C# 检测显示器被移除,将界面在当前可用的显示器上显示,避免程序在任务栏点击无响应。
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;
}
}
}
调用例子方法
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会弹出解决方法,选择弹出的解决方式。