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

如何在MAUI(iOS和Windows平台)截取含副屏的全屏截图

MAUI实现包含副屏的全屏截图方案

MAUI内置的Screenshot.Default.CaptureAsync()仅能捕获应用自身界面,要实现包含副屏的全屏截图,需依赖各平台原生API进行定制开发,以下是各主流平台的实现方案:

Windows平台

利用Windows.Graphics.Capture API实现多显示器捕获,支持直接获取所有显示设备的画面:

using Windows.Graphics.Capture;
using Windows.Media.Capture;
using Windows.Storage;
using Windows.UI.Core;

public async Task CaptureAllMonitors()
{
    // 获取系统中所有显示监视器
    var allMonitors = await GraphicsCaptureMonitor.GetAllMonitorsAsync();
    if (allMonitors.Count == 0) return;

    foreach (var monitor in allMonitors)
    {
        var captureItem = GraphicsCaptureItem.CreateFromMonitor(monitor);
        var captureSession = new GraphicsCaptureSession(captureItem);
        
        // 开启鼠标捕获
        captureSession.IsCursorCaptureEnabled = true;
        
        // 创建帧池,指定捕获格式与尺寸
        var framePool = Direct3D11CaptureFramePool.Create(
            GraphicsCaptureHelper.GetDevice(),
            DirectXPixelFormat.B8G8R8A8UIntNormalized,
            2,
            captureItem.Size);
        
        var frameReader = framePool.CreateFrameReader();
        frameReader.FrameArrived += async (sender, args) =>
        {
            using var capturedFrame = frameReader.TryGetNextFrame();
            if (capturedFrame == null) return;

            // 将捕获帧保存为PNG文件
            var saveFile = await KnownFolders.PicturesLibrary.CreateFileAsync(
                $"Monitor_{monitor.DisplayId}_Capture.png", 
                CreationCollisionOption.ReplaceExisting);
            await GraphicsCaptureHelper.SaveFrameToFile(capturedFrame, saveFile);
        };
        
        // 启动捕获
        captureSession.StartCapture();
        // 延迟确保捕获完成(可根据需求调整或通过事件触发停止)
        await Task.Delay(1000);
        // 释放资源
        captureSession.Close();
        framePool.Close();
        frameReader.Dispose();
    }
}

注意事项:

  • 需要在Package.appxmanifest中添加graphicsCapture权限
  • 需确保应用拥有文件读写权限

Android平台

通过MediaProjection API实现全屏捕获,需先获取用户授权:

1. 请求屏幕捕获权限

using Android.App;
using Android.Content;
using Android.Media;
using Android.OS;
using Android.Views;

private const int ScreenCaptureRequestCode = 1001;
private MediaProjection _mediaProjection;

public void RequestFullScreenCapturePermission()
{
    var projectionManager = (MediaProjectionManager)Android.App.Application.Context
        .GetSystemService(Context.MediaProjectionService);
    var captureIntent = projectionManager.CreateScreenCaptureIntent();
    ((Activity)Platform.CurrentActivity).StartActivityForResult(captureIntent, ScreenCaptureRequestCode);
}

2. 处理授权结果并启动捕获

protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
    base.OnActivityResult(requestCode, resultCode, data);
    if (requestCode == ScreenCaptureRequestCode && resultCode == Result.Ok)
    {
        var projectionManager = (MediaProjectionManager)Android.App.Application.Context
            .GetSystemService(Context.MediaProjectionService);
        _mediaProjection = projectionManager.GetMediaProjection((int)resultCode, data);
        StartScreenCapture();
    }
}

private void StartScreenCapture()
{
    var displayMetrics = new DisplayMetrics();
    Platform.CurrentActivity.WindowManager.DefaultDisplay.GetRealMetrics(displayMetrics);
    int screenWidth = displayMetrics.WidthPixels;
    int screenHeight = displayMetrics.HeightPixels;
    int screenDensity = displayMetrics.DensityDpi;

    // 创建ImageReader用于接收屏幕帧
    var imageReader = ImageReader.NewInstance(screenWidth, screenHeight, ImageFormatType.Rgba8888, 2);
    _mediaProjection.CreateVirtualDisplay(
        "FullScreenCapture", 
        screenWidth, screenHeight, screenDensity, 
        DisplayFlags.Public, imageReader.Surface, null, null);

    // 设置帧可用监听
    imageReader.SetOnImageAvailableListener(new ScreenCaptureImageListener(this), null);
}

// 自定义帧处理监听器
private class ScreenCaptureImageListener : Java.Lang.Object, ImageReader.IOnImageAvailableListener
{
    private readonly MainPage _owner;
    public ScreenCaptureImageListener(MainPage owner) => _owner = owner;

    public void OnImageAvailable(ImageReader reader)
    {
        using var capturedImage = reader.AcquireNextImage();
        if (capturedImage == null) return;

        // 将Image转换为Bitmap
        var planes = capturedImage.Planes;
        var buffer = planes[0].Buffer;
        int pixelStride = planes[0].PixelStride;
        int rowStride = planes[0].RowStride;
        int rowPadding = rowStride - pixelStride * capturedImage.Width;

        var bitmap = Bitmap.CreateBitmap(
            capturedImage.Width + rowPadding / pixelStride, 
            capturedImage.Height, 
            Bitmap.Config.Argb8888);
        bitmap.CopyPixelsFromBuffer(buffer);

        // 保存图片到本地
        var savePath = Android.OS.Environment.GetExternalStoragePublicDirectory(
            Android.OS.Environment.DirectoryPictures).AbsolutePath;
        var saveFile = new Java.IO.File(savePath, "FullScreenCapture.png");
        using var fileStream = new FileStream(saveFile.AbsolutePath, FileMode.Create);
        bitmap.Compress(Bitmap.CompressFormat.Png, 100, fileStream);
        bitmap.Recycle();

        // 停止捕获
        _owner._mediaProjection.Stop();
    }
}

注意事项:

  • 在AndroidManifest.xml中添加权限:
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL" />
    
  • Android 10及以上版本需额外申请MANAGE_EXTERNAL_STORAGE权限

iOS平台

受iOS系统安全限制,仅能捕获当前应用在所有屏幕上的内容,无法捕获其他应用界面。可通过UIScreen API获取所有屏幕并捕获:

using UIKit;
using Foundation;
using Photos;

public async Task CaptureAllAppScreens()
{
    foreach (var screen in UIScreen.Screens)
    {
        var screenBounds = screen.Bounds;
        UIGraphics.BeginImageContextWithOptions(screenBounds.Size, false, screen.Scale);
        var graphicsContext = UIGraphics.GetCurrentContext();
        
        // 捕获屏幕层级内容
        screen.CaptureHierarchyWithOptions(graphicsContext, screenBounds, UIScreenCaptureOptions.IncludingWindows);
        
        var capturedImage = UIGraphics.GetImageFromCurrentImageContext();
        UIGraphics.EndImageContext();

        // 保存图片到本地
        var imageData = capturedImage.AsPNG();
        var docPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
        var saveFilePath = Path.Combine(docPath, $"Screen_{screen.DeviceName}_Capture.png");
        File.WriteAllBytes(saveFilePath, imageData);

        // 保存到相册(需先申请权限)
        var authStatus = await PHPhotoLibrary.RequestAuthorizationAsync();
        if (authStatus == PHAuthorizationStatus.Authorized)
        {
            PHPhotoLibrary.SharedPhotoLibrary.PerformChanges(() =>
            {
                PHAssetCreationRequest.CreateAssetFromImage(imageData);
            }, (success, error) =>
            {
                if (!success) Console.WriteLine(error?.LocalizedDescription);
            });
        }
    }
}

注意事项:

  • 需在Info.plist中添加NSPhotoLibraryAddUsageDescription权限描述
  • iOS系统限制,无法捕获非当前应用的屏幕内容

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 13:12:34