从UIElement生成BitmapSource

我试图生成一个基于UIElementBitmapFrame 。 这是我的function:

 private BitmapFrame RenderToBitmap2() { RenderTargetBitmap renderBitmap = new RenderTargetBitmap(200, 200, 96, 96, PixelFormats.Pbgra32); DrawingVisual drawingVisual = new DrawingVisual(); DrawingContext drawingContext = drawingVisual.RenderOpen(); VisualBrush aVisualBrush = new VisualBrush(GenerateTestStackPanel()); drawingContext.DrawRectangle(aVisualBrush, new Pen(Brushes.Green, 2), new Rect(new Size(150, 150))); drawingContext.Close(); renderBitmap.Render(drawingVisual); return BitmapFrame.Create(renderBitmap); } 

出于测试和调试的目的,我使用了一个额外的函数来创建一个简单的StackFrame,它应该创建一个可以表示的有效视觉元素:

 private StackPanel GenerateTestStackPanel() { // Create a red Ellipse. Ellipse myEllipse = new Ellipse(); myEllipse.Fill = Brushes.Green; myEllipse.StrokeThickness = 2; myEllipse.Stroke = Brushes.Black; // Set the width and height of the Ellipse. myEllipse.Width = 200; myEllipse.Height = 200; // Add the Ellipse to the StackPanel. StackPanel myStackPanel = new StackPanel(); myStackPanel.Children.Add(myEllipse); return myStackPanel; } 

由于某种原因,VisualBrush没有在DrawRetangle(…)函数中呈现。 我可以看到绿色边框,但没有别的。 另外,如果我用标准画笔换掉VisualBrush,它效果很好:

 drawingContext.DrawRectangle(Brushes.Plum, new Pen(Brushes.Green, 2), new Rect(new Size(150, 150))); 

提前致谢!

看一下这个从UIElement创建BitmapSource的另一种方法:

MSDN线程

我也一直试图让VisualBrush工作,没有任何运气,这使我进入这个线程。

 public static BitmapSource CreateBitmapSourceFromVisual( Double width, Double height, Visual visualToRender, Boolean undoTransformation) { if (visualToRender == null) { return null; } RenderTargetBitmap bmp = new RenderTargetBitmap((Int32)Math.Ceiling(width), (Int32)Math.Ceiling(height), 96, 96, PixelFormats.Pbgra32); if (undoTransformation) { DrawingVisual dv = new DrawingVisual(); using (DrawingContext dc = dv.RenderOpen()) { VisualBrush vb = new VisualBrush(visualToRender); dc.DrawRectangle(vb, null, new Rect(new Point(), new Size(width, height))); } bmp.Render(dv); } else { bmp.Render(visualToRender); } return bmp; } 

之前我有同样的问题,我想将UIElement内容复制到图像中,我在上面的答案中使用了相同的方法,它似乎工作正常,只有我遇到的问题,我希望它能够实时工作,所以我不得不深入挖掘,我发现一些关于使用Windows API将元素的内容复制到Bitmap的引用,然后这个位图必须转换为BitmapSource因此它可以在WPF中使用

到目前为止它工作正常,但似乎泄漏记忆(不确定这一点)。 我将尝试重用UIElement hwnd Handle和位图对象以获得更好的性能和内存泄漏(如果存在)

 [DllImport("gdi32.dll")] private static extern bool BitBlt( IntPtr hdcDest, // handle to destination DC int nXDest, // x-coord of destination upper-left corner int nYDest, // y-coord of destination upper-left corner int nWidth, // width of destination rectangle int nHeight, // height of destination rectangle IntPtr hdcSrc, // handle to source DC int nXSrc, // x-coordinate of source upper-left corner int nYSrc, // y-coordinate of source upper-left corner System.Int32 dwRop // raster operation code ); [DllImport("User32.dll")] public extern static System.IntPtr GetDC(System.IntPtr hWnd); [DllImport("User32.dll")] public extern static int ReleaseDC(System.IntPtr hWnd, System.IntPtr hDC); //modified to include hWnd //[DllImport("gdi32.dll")] //[return: MarshalAs(UnmanagedType.Bool)] //internal static extern bool DeleteObject(IntPtr hObject); private static Bitmap GetBitmapFromControl(Window element, int width, int height) { HwndSource hWnd = (HwndSource)HwndSource.FromVisual(element); System.IntPtr srcDC = GetDC(hWnd.Handle); Bitmap bm = new Bitmap(width, height); Graphics g = Graphics.FromImage(bm); System.IntPtr bmDC = g.GetHdc(); BitBlt(bmDC, 0, 0, bm.Width, bm.Height, srcDC, 0, 0, 0x00CC0020 /*SRCCOPY*/); ReleaseDC(hWnd.Handle, srcDC); g.ReleaseHdc(bmDC); g.Dispose(); return bm; } public static BitmapSource ToWpfBitmap(this Bitmap bitmap) { using (MemoryStream stream = new MemoryStream()) { bitmap.Save(stream, ImageFormat.Bmp); stream.Position = 0; BitmapImage result = new BitmapImage(); result.BeginInit(); // According to MSDN, "The default OnDemand cache option retains access to the stream until the image is needed." // Force the bitmap to load right now so we can dispose the stream. result.CacheOption = BitmapCacheOption.OnLoad; result.StreamSource = stream; result.EndInit(); result.Freeze(); //DeleteObject(bitmap.GetHbitmap()); bitmap.Dispose(); return result; } }