WPF中的Drawing


以前在用WinForm的時候,可以通過GDI+接口在窗體上動態繪制自定義的圖形。在WPF中有沒有對應的API呢,最近項目中用到了這個,在這里總結一下。

WPF中的Drawing主要提供了幾類API:

1. Drawing類型

image

該組類型主要用來對繪制的對象的描述。比如GeometryDrawing是描述一個幾何圖形的Drawing,它的Geometry屬性定義了它所描述的幾何圖形是什么樣子。(它可以是如下Geometry類型的派生類型的任何一種,GeometryGroup是對多個Geometry的組合)

image

與GeometryGroup一樣,DrawingGroup是對多個Drawing的組合。

2. DrawingContext類型

Drawing類型是以對象的形式來描述要繪制的圖形,文字或視頻。DrawingContext是通過存儲繪制命令的形式來對要繪制的對象進行描述。這種方式更加簡單。我們可以通過DrawingGroup.Open方法來得到一個DrawingContext,然后可以調用如下接口來進行操作。

image

探其究竟,其實DrawingContext僅僅是將對Drawing對象的創建與管理進行了包裝,然后提供了一組比較方便使用的接口而已。

看反編譯出來的代碼:

public override void DrawEllipse(Brush brush, Pen pen, Point center, AnimationClock centerAnimations, double radiusX, AnimationClock radiusXAnimations, double radiusY, AnimationClock radiusYAnimations)
    {
        this.VerifyApiNonstructuralChange();
        if ((brush != null) || (pen != null))
        {
            EllipseGeometry newFreezable = new EllipseGeometry(center, radiusX, radiusY) {
                CanBeInheritanceContext = this.CanBeInheritanceContext
            };
            this.SetupNewFreezable(newFreezable, ((centerAnimations == null) && (radiusXAnimations == null)) && (radiusYAnimations == null));
            if (centerAnimations != null)
            {
                newFreezable.ApplyAnimationClock(EllipseGeometry.CenterProperty, centerAnimations);
            }
            if (radiusXAnimations != null)
            {
                newFreezable.ApplyAnimationClock(EllipseGeometry.RadiusXProperty, radiusXAnimations);
            }
            if (radiusYAnimations != null)
            {
                newFreezable.ApplyAnimationClock(EllipseGeometry.RadiusYProperty, radiusYAnimations);
            }
            this.AddNewGeometryDrawing(brush, pen, newFreezable);
        }
    }

private void AddNewGeometryDrawing(Brush brush, Pen pen, Geometry geometry)
{
    GeometryDrawing newFreezable = new GeometryDrawing {
        CanBeInheritanceContext = this.CanBeInheritanceContext,
        Brush = brush,
        Pen = pen,
        Geometry = geometry
    };
    this.SetupNewFreezable(newFreezable, (((brush == null) || brush.IsFrozen) && ((pen == null) || pen.IsFrozen)) && geometry.IsFrozen);
    this.AddDrawing(newFreezable);
}

private void AddDrawing(Drawing newDrawing)
{
    if (this._rootDrawing == null)
    {
        this._rootDrawing = newDrawing;
    }
    else if (this._currentDrawingGroup == null)
    {
        this._currentDrawingGroup = new DrawingGroup();
        this._currentDrawingGroup.CanBeInheritanceContext = this.CanBeInheritanceContext;
        this.SetupNewFreezable(this._currentDrawingGroup, false);
        this._currentDrawingGroup.Children.Add(this._rootDrawing);
        this._currentDrawingGroup.Children.Add(newDrawing);
        this._rootDrawing = this._currentDrawingGroup;
    }
    else
    {
        this._currentDrawingGroup.Children.Add(newDrawing);
    }
}

3.接受Drawing作為Content的類型

可以通過這些類型來應用Drawing中描述的對象繪制。

主要有如下幾種:

(1)DrawingImage,結合Image控件可以將Drawing顯示在UI上

image

(2) DrawingBrush, 都有了Brush了,那就可以在仍何控件畫了。比如說作為控件的Background.

image

(3) DrawingVisual類型

image

通過該類型,可以將Drawing創建為一個Visual.然后可以將Visual提供給一VisualContainer(可以自定義從FrameworkElement派生的類型,然后重寫GetVisualChildVisualChildrenCount方法作為VisualContainer)作為其UI呈現。

結合RenderTargetBitmap和BitmapEncoder, 我們可以將Drawing呈現到Bitmap圖片文件中。

image


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM