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

如何在WPF或Windows Forms中使用UWP的MediaCapture API?

在Windows Forms/WPF中使用UWP MediaCapture API的实现方案

从Windows 10 1803(Build 17134)开始,UWP的MediaCapture API可通过WinRT互操作在Windows Forms或WPF应用中使用,前提是应用目标框架为.NET Framework 4.6.1+、.NET Core 3.0+或.NET 5+,且运行在符合版本的Windows系统上。

一、项目前置配置

  1. 右键项目 → 属性 → 应用程序,将目标框架设置为.NET Framework 4.6.1及以上(或.NET 5+更推荐)
  2. 添加WinRT引用:右键项目 → 添加 → 引用 → 浏览,找到路径C:\Program Files (x86)\Windows Kits\10\UnionMetadata\10.0.xxx.0\Windows.winmd(替换xxx为你安装的SDK版本),添加该文件
  3. 启用不安全代码:在项目属性的生成选项卡,勾选“允许不安全代码”(WinRT互操作部分场景需要)

二、Windows Forms实现步骤

1. 界面准备

在窗体上添加一个PictureBox控件,用于显示摄像头预览画面。

2. 核心代码实现

using Windows.Media.Capture;
using Windows.Media.Devices;
using Windows.Media.MediaProperties;
using Windows.UI.Xaml.Media.Imaging;
using System.Threading.Tasks;
using System.Linq;

private MediaCapture _mediaCapture;
private bool _isCapturing = false;

// 初始化MediaCapture并启动预览
private async Task InitializeMediaCaptureAsync()
{
    _mediaCapture = new MediaCapture();
    var videoDevices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);
    if (!videoDevices.Any())
    {
        MessageBox.Show("未检测到摄像头设备");
        return;
    }

    var initSettings = new MediaCaptureInitializationSettings
    {
        StreamingCaptureMode = StreamingCaptureMode.Video,
        VideoDeviceId = videoDevices.First().Id
    };

    await _mediaCapture.InitializeAsync(initSettings);

    // 设置预览分辨率
    var previewProfile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.Vga);
    await _mediaCapture.VideoDeviceController.SetMediaStreamPropertiesAsync(
        MediaStreamType.VideoPreview, previewProfile.Video);

    // 启动预览并定时更新PictureBox
    var previewSink = new Windows.UI.Xaml.Controls.CaptureElement { Source = _mediaCapture };
    await _mediaCapture.StartPreviewAsync();

    var renderBitmap = new RenderTargetBitmap();
    var updateTimer = new System.Windows.Forms.Timer { Interval = 33 }; // 约30帧/秒
    updateTimer.Tick += async (s, e) =>
    {
        if (!_isCapturing) return;

        await renderBitmap.RenderAsync(previewSink);
        var pixelBuffer = await renderBitmap.GetPixelsAsync();
        
        // 转换为WinForms Bitmap并更新控件
        pictureBox1.Image?.Dispose();
        using (var stream = new System.IO.MemoryStream(pixelBuffer.ToArray()))
        {
            pictureBox1.Image = System.Drawing.Bitmap.FromStream(stream);
        }
    };
    updateTimer.Start();
}

// 窗体加载时初始化
private async void Form1_Load(object sender, EventArgs e)
{
    // 请求摄像头权限
    var accessStatus = await DeviceAccessInformation.CreateFromDeviceClass(DeviceClass.VideoCapture).RequestAccessAsync();
    if (accessStatus != DeviceAccessStatus.Allowed)
    {
        MessageBox.Show("需要授予摄像头权限才能使用");
        return;
    }

    try
    {
        await InitializeMediaCaptureAsync();
        _isCapturing = true;
    }
    catch (Exception ex)
    {
        MessageBox.Show($"初始化失败: {ex.Message}");
    }
}

// 窗体关闭时清理资源
private async void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    if (_isCapturing && _mediaCapture != null)
    {
        await _mediaCapture.StopPreviewAsync();
        _mediaCapture.Dispose();
        _isCapturing = false;
    }
}

三、WPF实现步骤

1. 界面准备

在XAML窗口中添加一个Image控件,用于显示摄像头预览:

<Image x:Name="imgPreview" Stretch="Uniform" />

2. 核心代码实现

using Windows.Media.Capture;
using Windows.Media.Devices;
using Windows.Media.MediaProperties;
using Windows.Graphics.Imaging;
using System.Windows.Media.Imaging;
using System.Linq;

private MediaCapture _mediaCapture;
private bool _isCapturing = false;

// 初始化MediaCapture并启动预览
private async Task InitializeMediaCaptureAsync()
{
    _mediaCapture = new MediaCapture();
    var videoDevices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);
    if (!videoDevices.Any())
    {
        MessageBox.Show("未检测到摄像头设备");
        return;
    }

    var initSettings = new MediaCaptureInitializationSettings
    {
        StreamingCaptureMode = StreamingCaptureMode.Video,
        VideoDeviceId = videoDevices.First().Id
    };

    await _mediaCapture.InitializeAsync(initSettings);

    // 设置预览分辨率
    var previewProfile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.Vga);
    await _mediaCapture.VideoDeviceController.SetMediaStreamPropertiesAsync(
        MediaStreamType.VideoPreview, previewProfile.Video);

    await _mediaCapture.StartPreviewAsync();

    // 定时获取预览帧并更新Image控件
    var updateTimer = new System.Timers.Timer(33);
    updateTimer.Elapsed += async (s, e) =>
    {
        if (!_isCapturing) return;

        using (var previewFrame = await _mediaCapture.GetPreviewFrameAsync())
        using (var softwareBitmap = previewFrame.SoftwareBitmap)
        {
            if (softwareBitmap == null) return;

            // 转换为WPF支持的像素格式
            using (var convertedBitmap = SoftwareBitmap.Convert(
                softwareBitmap, BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied))
            {
                var bitmapSource = new SoftwareBitmapSource();
                await bitmapSource.SetBitmapAsync(convertedBitmap);

                // 切换到UI线程更新控件
                Application.Current.Dispatcher.Invoke(() =>
                {
                    imgPreview.Source = bitmapSource;
                });
            }
        }
    };
    updateTimer.Start();
}

// 窗口加载时初始化
private async void Window_Loaded(object sender, RoutedEventArgs e)
{
    // 请求摄像头权限
    var accessStatus = await DeviceAccessInformation.CreateFromDeviceClass(DeviceClass.VideoCapture).RequestAccessAsync();
    if (accessStatus != DeviceAccessStatus.Allowed)
    {
        MessageBox.Show("需要授予摄像头权限才能使用");
        return;
    }

    try
    {
        await InitializeMediaCaptureAsync();
        _isCapturing = true;
    }
    catch (Exception ex)
    {
        MessageBox.Show($"初始化失败: {ex.Message}");
    }
}

// 窗口关闭时清理资源
private async void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
    if (_isCapturing && _mediaCapture != null)
    {
        await _mediaCapture.StopPreviewAsync();
        _mediaCapture.Dispose();
        _isCapturing = false;
    }
}

四、关键注意事项

  • 系统版本限制:必须运行在Windows 10 1803(Build 17134)及以上版本,否则WinRT互操作不支持MediaCapture API
  • 权限处理:必须获取摄像头访问权限,代码中已包含权限请求逻辑;若将应用打包为MSIX,需在Package.appxmanifest中添加摄像头权限声明
  • 内存管理:务必在应用关闭时释放MediaCapture资源,避免内存泄漏
  • 异步操作:WinRT API多为异步实现,需正确使用async/await,避免阻塞UI线程

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 19:35:26