문제

나는 a를 생성하려고한다 BitmapFrame 그것은 a UIElement. 내 기능은 다음과 같습니다.

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);
}

테스트 및 디버깅 목적으로 간단한 스택 프레임을 만드는 추가 기능을 사용하고 있습니다. ~해야 한다 표현할 수있는 유효한 시각적 요소를 만듭니다.

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)));

미리 감사드립니다!

도움이 되었습니까?

해결책

대체 방법을 위해 이것을 살펴보십시오. BitmapSource a UIElement:

MSDN 스레드

나는 또한이 스레드에 나를 데려온 운이없는 비주얼 브러쉬가 작동하도록 노력하고 있습니다.

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 이미지에 위의 답변에서 동일한 접근 방식을 사용했는데 잘 작동하는 것 같습니다. 문제 만있는 것만으로도 실시간으로 작동하기를 원했기 때문에 더 깊이 파고 들었습니다. 요소의 내용을 비트 맵으로 복사 한 다음이 비트 맵을 BitmapSource 따라서 WPF에서는 사용할 수 있습니다

지금까지는 잘 작동하지만 메모리가 새는 것 같습니다 (확실하지 않음). 나는 재사용하려고 노력할 것이다 UIElement 더 나은 성능 및 메모리 누출을위한 HWND 핸들 및 비트 맵 객체 (존재하는 경우)

[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;
    }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top