将矢量绘图传递给UI线程

时间:2011-09-15 09:44:26

标签: wpf graphics asynchronous

有没有办法在屏幕外的单独线程中使用Freezables绘制实际的WPF矢量图形(DrawingContext,VisualBrush,DrawingBrush,RenderTargetBitmap等)?

以下解决方案几乎拥有它,表示绘图是位图,并且当this.label变大时你的像素不可伸缩。

private void Draw()
{
    this.dispatcher = Dispatcher.CurrentDispatcher;
    Thread t = new Thread(this.DrawAsync);
    t.SetApartmentState(ApartmentState.STA);
    t.Start();
}

private void DrawAsync(object state)
{
    var b1 = new Button
        {
            Width = 50, 
            Height = 50, 
            Content = new TextBlock
                {
                    FontSize = 16, FontFamily = new FontFamily("Arial"), FontWeight = FontWeights.Bold, Text = "Hello"
                }
        };
    b1.Measure(new Size(50, 50));
    b1.Arrange(new Rect(0, 0, 50, 50));
    PixelFormat pixelFormat = PixelFormats.Default;
    var elementBrush = new VisualBrush(b1);
    var visual = new DrawingVisual();
    using (var dc = visual.RenderOpen())
    {
        // preferably I'd like to draw controls too, but shapes and text would suffice too
        dc.DrawRectangle(elementBrush, null, new Rect(0, 0, 50, 50));
        dc.DrawEllipse(Brushes.Green, new Pen(Brushes.Black, 2), new Point(75, 25), 25, 15);
        dc.Close();
    }

    var bitmap = new RenderTargetBitmap(100, 50, 96, 96, pixelFormat);
    bitmap.Render(visual);
    bitmap.Freeze();
    var br = new ImageBrush(bitmap) { Stretch = Stretch.Uniform };
    br.Freeze();
    this.dispatcher.Invoke((ThreadStart)delegate { this.label.Background = br; });
}        

1 个答案:

答案 0 :(得分:1)

您可以使用DrawingImage这是一种可冻结的类型。在BackgroundWorker中加载或填充它,将其冻结并将其传递给已完成事件中的图像。