如何在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
相关产品推荐
相关产品推荐

