目前博客園中成系列的Direct2D的教程有
1、萬一的 Direct2D 系列,用的是Delphi 2009
2、zdd的 Direct2D 系列,用的是VS中的C++
3、本文所在的 Direct2D教程 系列,用的是VS2010的Visual Basic語言(可以很方便的轉為C#),基於Windows API Code Pack 1.1。
還有官方的說明文檔 Direct2D ,用的是C++。
在Direct2D中不再區分筆刷(Brush)對象和畫筆(Pen)對象,統一用筆刷(Brush)對象。這樣,在繪制時候,無論是以Draw開頭的函數還是以Fill開頭的函數都使用筆刷(Brush)對象。
在Direct2D中,RenderTarget對象相當於畫布,Geometry等(還有文字、圖像等對象)對象相當於繪畫的內容,而Brush對象相當於繪畫的工具。使用Direct2D就是用工具把內容畫到畫布上。本文就詳細介紹筆刷(Brush)對象
Direct2D中的筆刷(Brush)的類型
純色筆刷(SolidColorBrush):使用一種顏色的筆刷。用一種顏色繪制內容。
線性漸變筆刷(LinearGradientBrush):使用兩種或多種顏色且是線性漸變的筆刷。用線性漸變的顏色填充需要繪制的區域
徑向漸變筆刷(RadialGradientBrush):使用兩種或多種顏色且是徑向漸變的筆刷。用徑向漸變的顏色填充需要繪制的區域
位圖筆刷(BitmapBrush):使用位圖的筆刷。用位圖填充需要繪制的區域
本文主要介紹前三種筆刷,位圖筆刷(BitmapBrush)留待后文詳解
純色筆刷(SolidColorBrush)
在Direct2D中,所有的筆刷(Brush)對象都繼承自類Brush,純色筆刷(SolidColorBrush)也不例外。筆刷(Brush)對象不能獨自實例化,必須通過RenderTarget對象的對應的函數創建而成。純色筆刷(SolidColorBrush)是由RenderTarget對象的CreateSolidColorBrush函數創建而成。
來看看CreateSolidColorBrush函數的原型定義
Public Function CreateSolidColorBrush(color As Direct2D1. ColorF) As Direct2D1. SolidColorBrush
Public Function CreateSolidColorBrush(color As Direct2D1. ColorF, brushProperties As Direct2D1. BrushProperties) As Direct2D1. SolidColorBrush
CreateSolidColorBrush函數的原型定義中,傳入一個ColorF的參數和BrushProperties參數
在Direct2D中,用結構ColorF表示顏色,它有四個分量,分別是Red、Green、Blue表示三種顏色的分量和Alpha表示不透明度的分量,分量的取值范圍在0-1之間。
還有一個結構ColorI也表示顏色,和ColorF類似,只是分量的范圍在0-255之間的整數。在實際使用中,ColorI僅僅起到輔助作用,最后還是要轉換為ColorF。
來看看結構ColorF的構造函數的原型定義
Direct2D1. ColorF(red As Single, green As Single, blue As Single)
Direct2D1. ColorF(red As Single, green As Single, blue As Single, alpha As Single)
Direct2D1. ColorF(argb As Integer)
Direct2D1. ColorF(colorValues As Single(), alpha As Single)
Direct2D1. ColorF(colorValues As Single())
Direct2D1. ColorF(color As Direct2D1. ColorI)
上面的原型定義中,如果不指定參數alpha,則分量Alpha默認值是1。
在第三個函數中,可以通過系統中的Color結構獲得某些系統指定的顏色。例如:Direct2D1.ColorF(Color.Aqua.ToArgb())獲得系統中名為Aqua的顏色。需要注意的是,如果是手動傳入參數的話,得是8位的16進制的數,每2位表示一個分量,例如:&HFF9ACD32
第四個和第五個函數中的數組中元素數不能少於3個。第五個函數數組元素數是4個的話,第四個元素指的是Alpha分量,如果元素數不是4個(3、5等其他值),則Alpha分量為1。
再看看結構BrushProperties的構造函數的原型定義
Direct2D1. BrushProperties(opacity As Single, transform As Direct2D1. Matrix3x2F)
參數opacity指的是不透明度,參數transform指的是變換矩陣。不過BrushProperties對純色筆刷(SolidColorBrush)沒啥太大的用處。貌似該參數僅僅對位圖筆刷(BitmapBrush)有用,而其他的筆刷則通過構造函數能完成該參數實現的效果。
下面是純色筆刷(SolidColorBrush)的示例,先用RenderTarget對象的clear方法(白色)清除畫布,再用黑色描邊,用綠色(&HFF9ACD32)填充
Public Class clsDirect2DSample6
Inherits clsDirect2DSample
Public Shadows Sub Render()
If Not _renderTarget Is Nothing Then
With _renderTarget
.BeginDraw()
Dim B As Direct2D1. SolidColorBrush = _renderTarget.CreateSolidColorBrush( New Direct2D1. ColorF( Color.Black.ToArgb))
Dim FB As Direct2D1. SolidColorBrush = _renderTarget.CreateSolidColorBrush( New Direct2D1. ColorF(&HFF9ACD32))
Dim R As New Direct2D1. RectF(30, 30, 200, 200)
.Clear( New Direct2D1. ColorF(1, 1, 1))
.DrawRectangle(R, B, 3)
.FillRectangle(R, FB)
.EndDraw()
End With
End If
End Sub
End Class
下圖是效果圖
線性漸變筆刷(LinearGradientBrush)
自GDI+開始,就引入了擴展筆刷(線性漸變筆刷(LinearGradientBrush)、徑向漸變筆刷(RadialGradientBrush)、位圖筆刷(BitmapBrush))。
線性漸變筆刷(LinearGradientBrush)就像是PS中的“漸變工具”
我們回顧下如何在PS中使用“漸變工具”
先是在漸變編輯器界面中,設置漸變顏色,如下圖
然后在畫布上,用漸變工具拖動(相當於設置漸變效果的起點和終點)完成漸變效果
線性漸變筆刷(LinearGradientBrush)也是類似的,先要完成漸變顏色的設置,然后設置筆刷的起點和終點。才能正常使用該筆刷。
先看看線性漸變筆刷(LinearGradientBrush)對應的RenderTarget對象的CreateLinearGradientBrush函數的原型定義
Public Function CreateLinearGradientBrush( _
linearGradientBrushProperties As Direct2D1. LinearGradientBrushProperties, _
gradientStopCollection As Direct2D1. GradientStopCollection _
) As Direct2D1. LinearGradientBrush
Public Function CreateLinearGradientBrush( _
linearGradientBrushProperties As Direct2D1. LinearGradientBrushProperties, _
gradientStopCollection As Direct2D1. GradientStopCollection, _
brushProperties As Direct2D1. BrushProperties _
) As Direct2D1. LinearGradientBrush
Public Sub Direct2D1. LinearGradientBrushProperties(startPoint As Direct2D1. Point2F, endPoint As Direct2D1. Point2F)
Public Sub Direct2D1. GradientStop(position As Single, color As Direct2D1. ColorF)
從上面的函數的原型定義來看,主要是傳遞了兩個參數:一是LinearGradientBrushProperties結構,定義了該筆刷的起點和終點(在畫布上的位置);二是GradientStopCollection類,包含了一個GradientStop的集合。每個GradientStop對象表示漸變軸上的一個顏色點,從GradientStop的原型定義來看,傳遞了兩個參數,position表明漸變軸上顏色點的位置,范圍是0-1,0表示起點的顏色,1表示終點的顏色;color表明該顏色點的顏色。下圖很好闡述了這些參數的意義
GradientStopCollection對象也必須依靠RenderTarget對象的CreateGradientStopCollection函數創建,下面看看CreateGradientStopCollection函數的原型定義
Public Function CreateGradientStopCollection( _
gradientStops As IEnumerable( Of Direct2D1. GradientStop), _
extendMode As Direct2D1. ExtendMode _
) As Direct2D1. GradientStopCollection
Public Enum Gamma
Linear = 1
StandardRgb = 0
End Enum
Public Enum ExtendMode
Mirror = 2
Wrap = 1
Clamp = 0
End Enum
該原型定義中,參數gradientStops表示一個GradientStop集合,每個GradientStop表示漸變軸上的一個顏色點。參數colorInterpolationGamma是枚舉Gamma,表示兩種顏色間的插值算法,可以試試兩種算法之間的差異。
參數extendMode是枚舉ExtendMode,表示超出筆刷范圍外的擴展模式,有Clamp(延伸:按照筆刷邊界點的顏色延伸)、Wrap(換行:按筆刷的方向重新設置顏色)、Mirror(鏡像:按筆刷的反方向重新設置顏色),在下面的示例中,我們看看這幾個擴展模式的區別
使用線性漸變筆刷(LinearGradientBrush)步驟
1、創建GradientStop集合,並添加若干GradientStop
2、創建GradientStopCollection對象
2、創建LinearGradientBrushProperties,設置線性漸變的起點、終點
3、利用步驟2和步驟3創建的對象創建線性漸變筆刷(LinearGradientBrush)
下面是示例代碼
Public Class clsDirect2DSample7
Inherits clsDirect2DSample
Public Shadows Sub Render()
If Not _renderTarget Is Nothing Then
With _renderTarget
.BeginDraw()
Dim B As Direct2D1. SolidColorBrush = _renderTarget.CreateSolidColorBrush( New Direct2D1. ColorF( Color.Black.ToArgb))
Dim LGB As Direct2D1. LinearGradientBrush
Dim G As New List( Of Direct2D1. GradientStop)
G.Add( New Direct2D1. GradientStop(0, New Direct2D1. ColorF( Color.Yellow.ToArgb)))
G.Add( New Direct2D1. GradientStop(1, New Direct2D1. ColorF( Color.ForestGreen.ToArgb)))
Dim GS As Direct2D1. GradientStopCollection
Dim R As Direct2D1. RectF
Dim LP As Direct2D1. LinearGradientBrushProperties
.Clear( New Direct2D1. ColorF(1, 1, 1))
R = New Direct2D1. RectF(30, 30, 190, 190)
LP = New Direct2D1. LinearGradientBrushProperties( New Direct2D1. Point2F(30, 30), New Direct2D1. Point2F(190, 190))
GS = _renderTarget.CreateGradientStopCollection(G, Direct2D1. Gamma.StandardRgb, Direct2D1. ExtendMode.Clamp)
LGB = _renderTarget.CreateLinearGradientBrush(LP, GS)
.DrawRectangle(R, B, 3)
.FillRectangle(R, LGB)
R = New Direct2D1. RectF(250, 30, 410, 190)
LP = New Direct2D1. LinearGradientBrushProperties( New Direct2D1. Point2F(250, 30), New Direct2D1. Point2F(330, 110))
GS = _renderTarget.CreateGradientStopCollection(G, Direct2D1. Gamma.StandardRgb, Direct2D1. ExtendMode.Clamp)
LGB = _renderTarget.CreateLinearGradientBrush(LP, GS)
.DrawRectangle(R, B, 3)
.FillRectangle(R, LGB)
R = New Direct2D1. RectF(30, 250, 190, 410)
LP = New Direct2D1. LinearGradientBrushProperties( New Direct2D1. Point2F(30, 250), New Direct2D1. Point2F(110, 330))
GS = _renderTarget.CreateGradientStopCollection(G, Direct2D1. Gamma.StandardRgb, Direct2D1. ExtendMode.Wrap)
LGB = _renderTarget.CreateLinearGradientBrush(LP, GS)
.DrawRectangle(R, B, 3)
.FillRectangle(R, LGB)
R = New Direct2D1. RectF(250, 250, 410, 410)
LP = New Direct2D1. LinearGradientBrushProperties( New Direct2D1. Point2F(250, 250), New Direct2D1. Point2F(330, 330))
GS = _renderTarget.CreateGradientStopCollection(G, Direct2D1. Gamma.StandardRgb, Direct2D1. ExtendMode.Mirror)
LGB = _renderTarget.CreateLinearGradientBrush(LP, GS)
.DrawRectangle(R, B, 3)
.FillRectangle(R, LGB)
.EndDraw()
End With
End If
End Sub
End Class
下圖是示例代碼的運行效果圖
上圖中,先設置了一個從黃色到綠色的線性漸變。
左上角的矩形中,矩形的范圍(30,30,190,190),漸變的起點是(30,30)、終點(190,190),漸變從矩形的左上角到矩形的右下角
右上角的矩形中,矩形的范圍(250,30,410,190),漸變的起點是(250,30)、終點(330,110),矩形以對角線為界,上面是漸變部分,下面是擴展部分。擴展模式設置為Clamp(延伸),擴展部分的顏色就是漸變邊界(對角線)的顏色
左下角的矩形中,矩形的范圍(30,250,190,410),漸變的起點是(30,250)、終點(110,330),矩形以對角線為界,上面是漸變部分,下面是擴展部分。擴展模式設置為Wrap(換行),擴展部分的顏色就是重新開始的一個漸變(漸變方向不變)
右下角的矩形中,矩形的范圍(250,250,410,410),漸變的起點是(250,250)、終點(330,330),矩形以對角線為界,上面是漸變部分,下面是擴展部分。擴展模式設置為Mirror(鏡像),擴展部分的顏色就是重新開始的一個漸變(漸變方向改變)
下圖是擴展模式分別為Wrap(換行,上面的矩形)和Mirror(鏡像,下面的矩形)的有趣的示意圖。代碼就不貼出來了。
徑向漸變筆刷(RadialGradientBrush)
徑向漸變和線性漸變類似,都是顏色的漸變,只不過徑向的漸變是以橢圓為基准,起點是橢圓的內部點(一般是中心),終點是橢圓的邊界,橢圓邊界外部的區域為擴展區域。
先看看徑向漸變筆刷(RadialGradientBrush)對應的RenderTarget對象的CreateRadialGradientBrush函數的原型定義
Public Function CreateRadialGradientBrush( _
radialGradientBrushProperties As Direct2D1. RadialGradientBrushProperties, _
gradientStopCollection As Direct2D1. GradientStopCollection _
) As Direct2D1. RadialGradientBrush
Public Function CreateRadialGradientBrush( _
radialGradientBrushProperties As Direct2D1. RadialGradientBrushProperties, _
gradientStopCollection As Direct2D1. GradientStopCollection, _
brushProperties As Direct2D1. BrushProperties _
) As Direct2D1. RadialGradientBrush
Direct2D1. RadialGradientBrushProperties(center As Direct2D1. Point2F, gradientOriginOffset As Direct2D1. Point2F, radiusX As Single, radiusY As Single)
從上面的函數的原型定義來看,主要是傳遞了兩個參數:一是RadialGradientBrushProperties結構,定義了該筆刷的中心點(橢圓的中心點)、偏移點(相對中心點的位置)和橢圓的橫軸半徑和縱軸半徑;二是GradientStopCollection類,包含了一個GradientStop的集合。
下圖闡述了偏移點對徑向漸變筆刷的影響
使用徑向漸變筆刷(RadialGradientBrush)步驟
1、創建GradientStop集合,並添加若干GradientStop
2、創建GradientStopCollection對象
2、創建RadialGradientBrushProperties,設置徑向漸變的中心點、偏移點、橫軸半徑、縱軸半徑等
3、利用步驟2和步驟3創建的對象創建線性漸變筆刷(RadialGradientBrush)
下面是示例代碼,偏移點設置為中心點的(-50,-50)處
Public Class clsDirect2DSample9
Inherits clsDirect2DSample
Public Shadows Sub Render()
If Not _renderTarget Is Nothing Then
With _renderTarget
.BeginDraw()
Dim B As Direct2D1. SolidColorBrush = _renderTarget.CreateSolidColorBrush( New Direct2D1. ColorF( Color.Black.ToArgb))
Dim G As New List( Of Direct2D1. GradientStop)
G.Add( New Direct2D1. GradientStop(0, New Direct2D1. ColorF(0.9, 0.9, 0.9)))
G.Add( New Direct2D1. GradientStop(1, New Direct2D1. ColorF( Color.ForestGreen.ToArgb)))
Dim GS As Direct2D1. GradientStopCollection
Dim RGB As Direct2D1. RadialGradientBrush
Dim RP As Direct2D1. RadialGradientBrushProperties
.Clear( New Direct2D1. ColorF(1, 1, 1))
RP = New Direct2D1. RadialGradientBrushProperties( New Direct2D1. Point2F(200, 200), New Direct2D1. Point2F(-50, -50), 120, 120)
GS = _renderTarget.CreateGradientStopCollection(G, Direct2D1. Gamma.StandardRgb, Direct2D1. ExtendMode.Clamp)
RGB = _renderTarget.CreateRadialGradientBrush(RP, GS)
Dim E As New Direct2D1. Ellipse( New Direct2D1. Point2F(200, 200), 120, 120)
.Clear( New Direct2D1. ColorF(1, 1, 1))
.DrawEllipse(E, B, 3)
.FillEllipse(E, RGB)
.EndDraw()
End With
End If
End Sub
End Class
下圖是示例代碼的效果圖
合理的運用各種筆刷,能實現各種效果,就看你們自己的想象發揮了。