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

如何在WPF中使用SharpDX将缓冲区渲染到指定元素?

解决WPF中SharpDX渲染到特定控件的问题

当前代码使用WindowRenderTarget直接绑定到窗口的HWND,导致渲染内容覆盖整个窗口。要渲染到WPF的特定控件(如Image或Canvas),推荐采用离屏渲染+WPF控件显示的方案,具体实现如下:

方案核心思路

先通过SharpDX的离屏渲染目标(BitmapRenderTarget)将内容绘制到位图,再将该位图转换为WPF原生的BitmapSource,最终赋值给目标控件的Source属性,完美适配WPF的控件布局体系。

修改后的完整代码

1. 调整初始化逻辑

移除绑定窗口HWND的WindowRenderTarget,保留D2D工厂和通用位图属性:

private SharpDX.Direct2D1.Factory1 _d2dFactory;
private BitmapProperties _bitmapProperties;

private void InitializeDirect2D()
{
    _d2dFactory = new SharpDX.Direct2D1.Factory1(FactoryType.MultiThreaded);
    _bitmapProperties = new BitmapProperties(
        new SharpDX.Direct2D1.PixelFormat(Format.B8G8R8A8_UNorm, SharpDX.Direct2D1.AlphaMode.Premultiplied)
    );
}

2. 修改绘制逻辑,渲染到离屏位图并绑定到WPF控件

public void DrawBitmapToImage(Image wpfImage, Frame frame) // Frame为自定义帧数据类型
{
    int width = frame.width;
    int height = frame.height;
    int stride = width * 4;
    IntPtr buffer = (IntPtr)frame.data[0];

    // 创建离屏渲染目标
    using (var renderTarget = new BitmapRenderTarget(
        _d2dFactory,
        new RenderTargetProperties
        {
            DpiX = 96,
            DpiY = 96,
            MinLevel = FeatureLevel.Level_DEFAULT,
            Type = RenderTargetType.Hardware,
            Usage = RenderTargetUsage.None
        },
        _bitmapProperties,
        width,
        height))
    {
        // 执行绘制操作
        renderTarget.BeginDraw();
        // 注意:D2D的RawColor4参数为0-1的浮点数,原代码的255会导致颜色异常
        RawColor4 clearColor = new RawColor4(1f, 1f, 1f, 1f); 
        renderTarget.Clear(clearColor);

        using (var stream = new DataStream(buffer, stride * height, true, false))
        {
            var sourceBitmap = new SharpDX.Direct2D1.Bitmap(renderTarget, new Size2(width, height), stream, stride, _bitmapProperties);
            renderTarget.DrawBitmap(sourceBitmap, 1.0f, SharpDX.Direct2D1.BitmapInterpolationMode.Linear);
            sourceBitmap.Dispose();
        }

        renderTarget.EndDraw();

        // 将D2D位图转换为WPF BitmapSource
        var d2dBitmap = renderTarget.Bitmap;
        var bitmapData = d2dBitmap.Map(MapOptions.Read);

        try
        {
            var wpfBitmap = BitmapSource.Create(
                width,
                height,
                96,
                96,
                PixelFormats.Bgra32,
                null,
                bitmapData.DataPointer,
                stride * height,
                stride
            );

            // 线程安全更新UI控件(渲染操作可能在非UI线程执行)
            if (wpfImage.Dispatcher.CheckAccess())
            {
                wpfImage.Source = wpfBitmap;
            }
            else
            {
                wpfImage.Dispatcher.Invoke(() => wpfImage.Source = wpfBitmap);
            }
        }
        finally
        {
            d2dBitmap.Unmap();
        }
    }
}

关键修改点说明

  • 替换渲染目标:移除WindowRenderTarget,改用BitmapRenderTarget做离屏渲染,避免直接绑定窗口HWND
  • 修正颜色值:D2D的RawColor4参数为0-1的浮点数,原代码的255会导致颜色异常
  • 线程安全处理:添加WPF控件的跨线程更新逻辑,适配渲染操作可能在后台线程执行的场景
  • 高效格式转换:直接映射D2D位图数据转换为WPF的BitmapSource,性能损耗极低

替代方案(绑定控件独立HWND)

如果需要直接渲染到控件的HWND(如自定义原生控件),需:

  • 自定义继承HwndHost的控件,重写BuildWindowCore创建独立HWND
  • 将WindowRenderTarget的Hwnd属性设置为该自定义控件的HWND
  • 监听控件尺寸变化事件,动态调整WindowRenderTarget的PixelSize

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 05:40:09