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

MAUI如何检测Windows PC所有屏幕?实现自定义屏幕弹窗需求

解决MAUI Windows平台多屏检测与窗口定位问题

由于MAUI的Microsoft.Maui.Devices.DeviceDisplay仅提供主屏幕信息,要实现多屏检测和指定屏幕显示窗口,需借助Windows原生API实现平台特定逻辑,以下是两种可行方案:

方案一:使用Win32 API枚举显示器

通过EnumDisplayMonitors Win32函数枚举所有连接的显示器,获取每个屏幕的分辨率、位置等信息。

步骤1:定义Win32结构体与导入函数

在Windows平台项目中添加以下代码:

using System.Runtime.InteropServices;

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

    [StructLayout(LayoutKind.Sequential)]
    public struct MONITORINFOEX
    {
        public int cbSize;
        public RECT rcMonitor;
        public RECT rcWork;
        public uint dwFlags;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string szDevice;
    }

    public delegate bool MonitorEnumDelegate(IntPtr hMonitor, IntPtr hdcMonitor, ref RECT lprcMonitor, IntPtr dwData);

    [DllImport("user32.dll")]
    public static extern bool EnumDisplayMonitors(IntPtr hdc, IntPtr lprcClip, MonitorEnumDelegate lpfnEnum, IntPtr dwData);

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

步骤2:枚举所有屏幕信息

编写方法获取所有屏幕的详细信息:

public List<(string DeviceName, int Width, int Height, int Left, int Top)> GetAllScreens()
{
    var screens = new List<(string, int, int, int, int)>();
    
    Win32DisplayHelper.MonitorEnumDelegate enumDelegate = (hMonitor, hdcMonitor, ref Win32DisplayHelper.RECT lprcMonitor, IntPtr dwData) =>
    {
        var monitorInfo = new Win32DisplayHelper.MONITORINFOEX();
        monitorInfo.cbSize = Marshal.SizeOf(monitorInfo);
        Win32DisplayHelper.GetMonitorInfo(hMonitor, ref monitorInfo);
        
        int width = monitorInfo.rcMonitor.Right - monitorInfo.rcMonitor.Left;
        int height = monitorInfo.rcMonitor.Bottom - monitorInfo.rcMonitor.Top;
        
        screens.Add((monitorInfo.szDevice, width, height, monitorInfo.rcMonitor.Left, monitorInfo.rcMonitor.Top));
        return true;
    };
    
    Win32DisplayHelper.EnumDisplayMonitors(IntPtr.Zero, IntPtr.Zero, enumDelegate, IntPtr.Zero);
    return screens;
}

方案二:使用Windows App SDK的DisplayManager

借助Windows App SDK的DisplayManager类获取显示设备信息,更适配现代Windows应用:

步骤1:安装Windows App SDK NuGet包

在项目中安装Microsoft.WindowsAppSDK包。

步骤2:获取所有显示设备

using Windows.Devices.Display;
using Windows.Devices.Display.Core;

public async Task<List<(string DisplayId, int Width, int Height)>> GetAllDisplaysAsync()
{
    var displays = new List<(string, int, int)>();
    var displayManager = DisplayManager.GetForCurrentView();
    await displayManager.RequestStartAsync();
    
    foreach (var display in displayManager.GetCurrentDisplays())
    {
        var resolution = display.CurrentMode.NativeResolution;
        displays.Add((display.DisplayId.ToString(), resolution.Width, resolution.Height));
    }
    
    await displayManager.RequestStopAsync();
    return displays;
}

将窗口定位到指定屏幕

获取屏幕信息后,可通过Win32 API移动MAUI窗口到目标屏幕:

using System.Runtime.InteropServices;

public static class WindowHelper
{
    [DllImport("user32.dll")]
    public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
    
    private const uint SWP_NOSIZE = 0x0001;
    private const uint SWP_NOZORDER = 0x0004;

    public static void MoveWindowToScreen(IntPtr windowHandle, int left, int top)
    {
        SetWindowPos(windowHandle, IntPtr.Zero, left, top, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
    }
}

// 在MAUI中调用:
var windowHandle = Window.Handler.PlatformView.Handle; // 获取当前窗口句柄
var targetScreen = GetAllScreens().First(s => s.DeviceName == "\\\\.\\DISPLAY2"); // 选择目标屏幕
WindowHelper.MoveWindowToScreen(windowHandle, targetScreen.Left, targetScreen.Top);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 08:10:29