筆刷概觀

本概觀描述如何建立和使用 ID2D1SolidColorBrushID2D1LinearGradientBrushID2D1RadialGradientBrushID2D1BitmapBrush 物件,以純色、漸層和點陣圖繪製區域。 包含以下幾節。

必要條件

此概觀假設您已熟悉基本 Direct2D 應用程式的結構,如 建立簡單的 Direct2D 應用程式中所述。

筆刷類型

筆刷會「繪製」具有其輸出的區域。 不同的筆刷有不同類型的輸出。 Direct2D 提供四種筆刷類型: ID2D1SolidColorBrush 以純色繪製區域、 ID2D1LinearGradientBrush 與線性漸層、 ID2D1RadialGradientBrush 搭配星形漸層,以及具有點陣圖的 ID2D1BitmapBrush

注意

從 Windows 8 開始,您也可以使用ID2D1ImageBrush,這類似于點陣圖筆刷,但您也可以使用基本類型。

所有筆刷都繼承自 ID2D1Brush ,並共用一組通用功能 (設定和取得不透明度,以及轉換筆刷) ;它們是由 ID2D1RenderTarget 所建立,而且是裝置相依的資源:您的應用程式應該在初始化筆刷之後建立筆刷,並在轉譯目標需要重新建立時重新建立筆刷。 (如需資源的詳細資訊,請參閱 資源概觀.)

下圖顯示每個不同筆刷類型的範例。

純色筆刷、線性漸層筆刷、星形漸層筆刷和點陣圖筆刷的視覺效果圖例

色彩基本概念

使用 ID2D1SolidColorBrush 或漸層筆刷繪製之前,您需要選擇色彩。 在 Direct2D 中,色彩會以 D2D1_COLOR_F 結構表示 (,這實際上只是 Direct3D、 D3DCOLORVALUE) 所使用之結構的新名稱。

在Windows 8之前,D2D1_COLOR_F會使用 sRGB 編碼。 sRGB 編碼會將色彩分成四個元件:紅色、綠色、藍色和 Alpha。 每個元件都是以一般範圍為 0.0 到 1.0 的浮點值代表。 值為 0.0 時,表示完全沒有該色彩,而值為 1.0 時,則表示全部為該色彩。 就 Alpha 元件而言,0.0 代表完全透明的色彩,1.0 則代表完全不透明的色彩。

從 Windows 8 開始,D2D1_COLOR_F也接受 scRGB 編碼。 scRGB 是 的超集合,允許色彩值高於 1.0 和低於 0.0。

若要定義色彩,您可以使用 D2D1_COLOR_F結構並 自行初始化其欄位,也可以使用 D2D1::ColorF 類別來協助您建立色彩。 ColorF類別提供數個建構函式來定義色彩。 如果未在建構函式中指定 Alpha 值,則預設為 1.0。

  • 使用 ColorF (Enum、FLOAT) 建構函式來指定預先定義的色彩和 Alpha 色板值。 Alpha 色板值的範圍從 0.0 到 1.0,其中 0.0 代表完全透明色彩,1.0 代表完全不透明色彩。 下圖顯示數個預先定義的色彩及其十六進位對等專案。 如需預先定義色彩的完整清單,請參閱 ColorF 類別的 Color 常數一節。

    預先定義色彩的圖例

    下列範例會建立預先定義的色彩,並使用它來指定 ID2D1SolidColorBrush的色彩。

hr = m_pRenderTarget->CreateSolidColorBrush(
    D2D1::ColorF(D2D1::ColorF::Black, 1.0f),
    &m_pBlackBrush
    );
  • 使用 ColorF (FLOAT、FLOAT、FLOAT、FLOAT) 建構函式來指定紅色、綠色、藍色和 Alpha 序列中的色彩,其中每個元素的值介於 0.0 和 1.0 之間。

    下列範例會指定色彩的紅色、綠色、藍色和 Alpha 值。

    ID2D1SolidColorBrush *pGridBrush = NULL;
    hr = pCompatibleRenderTarget->CreateSolidColorBrush(
        D2D1::ColorF(D2D1::ColorF(0.93f, 0.94f, 0.96f, 1.0f)),
        &pGridBrush
        );
    hr = m_pRenderTarget->CreateSolidColorBrush(
        D2D1::ColorF(D2D1::ColorF(0x9ACD32, 1.0f)),  
        &m_pYellowGreenBrush
        );

Alpha 模式

不論您使用筆刷之轉譯目標的 Alpha 模式為何, D2D1_COLOR_F 值一律會解譯為直接 Alpha。

使用純色筆刷

若要建立純色筆刷,請呼叫 ID2D1RenderTarget::CreateSolidColorBrush 方法,此方法會傳回 HRESULT 和 ID2D1SolidColorBrush 物件。 下圖顯示使用黑色筆刷繪製的方形,並使用純色筆刷繪製,其色彩值為 0x9ACD32。

使用純色筆刷繪製的正方形圖例

下列程式碼示範如何建立和使用黑色色彩筆刷,以及色彩值為 0x9ACD32 的筆刷,以填滿並繪製此方形。

    ID2D1SolidColorBrush *m_pBlackBrush;
    ID2D1SolidColorBrush *m_pYellowGreenBrush;
if (SUCCEEDED(hr))
{
    hr = m_pRenderTarget->CreateSolidColorBrush(
        D2D1::ColorF(D2D1::ColorF::Black, 1.0f),
        &m_pBlackBrush
        );
}

// Create a solid color brush with its rgb value 0x9ACD32.
if (SUCCEEDED(hr))
{
    hr = m_pRenderTarget->CreateSolidColorBrush(
        D2D1::ColorF(D2D1::ColorF(0x9ACD32, 1.0f)),  
        &m_pYellowGreenBrush
        );
}
m_pRenderTarget->FillRectangle(&rcBrushRect, m_pYellowGreenBrush);
m_pRenderTarget->DrawRectangle(&rcBrushRect, m_pBlackBrush, 1, NULL);

不同于其他筆刷,建立 ID2D1SolidColorBrush 是相對便宜的作業。 每次轉譯時,您可能會建立 ID2D1SolidColorBrush 物件,而不會影響效能。 不建議針對漸層或點陣圖筆刷使用此方法。

使用線性漸層筆刷

ID2D1LinearGradientBrush會繪製沿著線條、漸層軸定義線性漸層的區域。 您可以使用 ID2D1GradientStop 物件,在漸層軸上指定漸層色彩及其位置。 您也可以修改漸層軸,這可讓您建立水準和垂直漸層,以及反轉漸層方向。 若要建立線性漸層筆刷,請呼叫 ID2D1RenderTarget::CreateLinearGradientBrush 方法。

下圖顯示以 ID2D1LinearGradientBrush 繪製的方形,其具有兩個預先定義的色彩「Yellow」 和 「ForestGreen」。

以黃色和樹系綠色線性漸層筆刷繪製的方形圖例

若要建立上圖所示的漸層,請完成下列步驟:

  1. 宣告兩 個D2D1_GRADIENT_STOP 物件。 每個漸層停駐點都會指定色彩和位置。 0.0 的位置表示漸層的開頭,而 1.0 的位置則表示漸層的結尾。

    下列程式碼會建立兩個 D2D1_GRADIENT_STOP 物件的陣列。 第一個停駐點指定位置 0 的色彩 「Yellow」,而第二個停駐點指定位置 1 的色彩 「ForestGreen」。

    // Create an array of gradient stops to put in the gradient stop
    // collection that will be used in the gradient brush.
    ID2D1GradientStopCollection *pGradientStops = NULL;

    D2D1_GRADIENT_STOP gradientStops[2];
    gradientStops[0].color = D2D1::ColorF(D2D1::ColorF::Yellow, 1);
    gradientStops[0].position = 0.0f;
    gradientStops[1].color = D2D1::ColorF(D2D1::ColorF::ForestGreen, 1);
    gradientStops[1].position = 1.0f;
  1. 建立 ID2D1GradientStopCollection。 下列範例會呼叫 CreateGradientStopCollection、傳入 D2D1_GRADIENT_STOP 物件的陣列、 (2) 的漸層停駐點數目、 插入D2D1_GAMMA_2_2 ,以及擴充模式 的D2D1_EXTEND_MODE_CLAMP
    // Create the ID2D1GradientStopCollection from a previously
    // declared array of D2D1_GRADIENT_STOP structs.
    hr = m_pRenderTarget->CreateGradientStopCollection(
        gradientStops,
        2,
        D2D1_GAMMA_2_2,
        D2D1_EXTEND_MODE_CLAMP,
        &pGradientStops
        );
  1. 建立 ID2D1LinearGradientBrush。 下一個範例會呼叫 CreateLinearGradientBrush 方法,並傳遞線性漸層筆刷屬性,其中包含 (0、0) 的起點,以及 (150、150) ,以及上一個步驟中建立的漸層停駐點。
    // The line that determines the direction of the gradient starts at
    // the upper-left corner of the square and ends at the lower-right corner.

    if (SUCCEEDED(hr))
    {
        hr = m_pRenderTarget->CreateLinearGradientBrush(
            D2D1::LinearGradientBrushProperties(
                D2D1::Point2F(0, 0),
                D2D1::Point2F(150, 150)),
            pGradientStops,
            &m_pLinearGradientBrush
            );
    }
  1. 使用 ID2D1LinearGradientBrush。 下一個程式碼範例會使用筆刷填滿矩形。
    m_pRenderTarget->FillRectangle(&rcBrushRect, m_pLinearGradientBrush);

深入瞭解漸層停駐點

D2D1_GRADIENT_STOP是漸層筆刷的基本建置組塊。 漸層停駐點會指定漸層軸的色彩和位置。 漸層位置範圍介於 0.0 和 1.0 之間的值。 越接近 0.0,色彩越接近漸層的開頭;越接近 1.0,色彩越接近漸層的結尾。

下圖醒目提示漸層停駐點。 圓形會標示漸層停駐點的位置,而虛線會顯示漸層軸。

沿著軸四個停駐點的線性漸層筆刷圖例

第一個漸層停駐點指定位於 0.0 位置的黃色。 第二個漸層停駐點指定位於 0.25 位置的紅色。 從左至右沿著漸層軸,這兩個停駐點之間的色彩會逐漸從黃色變更為紅色。 第三個漸層停駐點指定位於 0.75 位置的藍色。 第二個和第三個漸層停駐點之間的色彩會逐漸從紅色變更為藍色。 第四個漸層停駐點會在 1.0 的位置指定綠色綠色。 第三層和第四個漸層停駐點之間的色彩會逐漸從藍色變更為綠色。

漸層軸

如先前所述,線性漸層筆刷的漸層停駐點會沿著線條排列,也就是漸層軸。 您可以在建立線性漸層筆刷時,使用D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES結構的startPointendPoint欄位來指定線條的方向和大小。 建立筆刷之後,您可以呼叫筆刷的 SetStartPointSetEndPoint 方法來調整漸層軸。 藉由操作筆刷的起點和終點,您可以建立水準和垂直漸層、反轉漸層方向等等。

例如,在下圖中,起點會設定為 (0,0) ,並將端點設定為 (150,50) ;這會建立從左上角開始的對角漸層,並延伸至所繪製區域的右下角。 當您將起點設定為 (0、25) ,並將端點設定為 (150、25) 時,會建立水準漸層。 同樣地,將起點設定為 (75、0) ,並將端點設定為 (75、50) 會建立垂直漸層。 將起點設定為 (0、50) ,並將端點設定為 (150,0) 會建立從左下角開始的對角漸層,並延伸至繪製區域的右上角。

相同矩形上四個不同的漸層軸圖例

使用星形漸層筆刷

不同于在漸層軸上混合兩個或多個色彩 的 ID2D1LinearGradientBrushID2D1RadialGradientBrush 會使用星形漸層繪製一個區域,在橢圓形之間混合兩個或多個色彩。 雖然 ID2D1LinearGradientBrush 使用起點和終點定義其漸層軸,但 ID2D1RadialGradientBrush 藉由指定中心、水準和垂直弧度和漸層原點位移來定義其漸層橢圓形。

如同 ID2D1LinearGradientBrushID2D1RadialGradientBrush 會使用 ID2D1GradientStopCollection 來指定漸層中的色彩和位置。

下圖顯示以 ID2D1RadialGradientBrush繪製的圓形。 圓形有兩個漸層停駐點:第一個在 0.0 的位置指定預先定義的色彩 「Yellow」,而第二個指定 1.0 位置的預先定義色彩 「ForestGreen」。 漸層的中心 (75、75) 、 (0、0) 的漸層原點位移,以及 x 和 y 半徑為 75。

使用星形漸層筆刷繪製的圓形圖例

下列程式碼範例示範如何使用 ID2D1RadialGradientBrush 繪製此圓形,其色彩停駐點為 0.0,而 「ForestGreen」 位於 1.0 的位置。 與建立 ID2D1LinearGradientBrush類似,此範例會呼叫 CreateGradientStopCollection ,從漸層停駐點陣列建立 ID2D1GradientStopCollection

// Create an array of gradient stops to put in the gradient stop
// collection that will be used in the gradient brush.
ID2D1GradientStopCollection *pGradientStops = NULL;

D2D1_GRADIENT_STOP gradientStops[2];
gradientStops[0].color = D2D1::ColorF(D2D1::ColorF::Yellow, 1);
gradientStops[0].position = 0.0f;
gradientStops[1].color = D2D1::ColorF(D2D1::ColorF::ForestGreen, 1);
gradientStops[1].position = 1.0f;
// Create the ID2D1GradientStopCollection from a previously
// declared array of D2D1_GRADIENT_STOP structs.
hr = m_pRenderTarget->CreateGradientStopCollection(
    gradientStops,
    2,
    D2D1_GAMMA_2_2,
    D2D1_EXTEND_MODE_CLAMP,
    &pGradientStops
    );

若要建立 ID2D1RadialGradientBrush,請使用 ID2D1RenderTarget::CreateRadialGradientBrush 方法。 CreateRadialGradientBrush會採用三個參數。 第一個參數, D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES 指定中心、漸層原點位移,以及漸層的水準和垂直弧度。 第二個參數是 ID2D1GradientStopCollection ,描述色彩及其在漸層中的位置,而第三個參數則是接收新 ID2D1RadialGradientBrush 參考的指標位址。 有些多載會採用額外的參數, D2D1_BRUSH_PROPERTIES 結構,指定要套用至新筆刷的不透明度值和轉換。

下一個範例會呼叫 CreateRadialGradientBrush、傳入漸層停駐點陣列,以及 將中心 值設定為 (75、75) 的星形漸層筆刷屬性、 將 gradientOriginOffset 設定為 (0、0) ,以及 radiusXradiusY 都設定為 75。

// The center of the gradient is in the center of the box.
// The gradient origin offset was set to zero(0, 0) or center in this case.
if (SUCCEEDED(hr))
{
    hr = m_pRenderTarget->CreateRadialGradientBrush(
        D2D1::RadialGradientBrushProperties(
            D2D1::Point2F(75, 75),
            D2D1::Point2F(0, 0),
            75,
            75),
        pGradientStops,
        &m_pRadialGradientBrush
        );
}

最後一個範例會使用筆刷來填滿橢圓形。

m_pRenderTarget->FillEllipse(ellipse, m_pRadialGradientBrush);
m_pRenderTarget->DrawEllipse(ellipse, m_pBlackBrush, 1, NULL);

設定星形漸層

中心gradientOriginOffsetradiusX和/或radiusY的不同值會產生不同的漸層。 下圖顯示數個具有不同漸層原點位移的星形漸層,建立從不同角度照亮圓形的光線外觀。

以不同原點位移繪製的相同圓形圖例

使用點陣圖筆刷

ID2D1BitmapBrush會繪製以ID2D1Bitmap物件表示之點陣圖 (的區域) 。

下圖顯示以植物點陣圖繪製的方形。

以植物點陣圖繪製之正方形的圖例

下列範例示範如何使用 ID2D1BitmapBrush繪製此方形。

第一個範例會初始化 ID2D1Bitmap 以搭配筆刷使用。 ID2D1Bitmap是由範例中其他地方定義的 Helper 方法 LoadResourceBitmap 所提供。

// Create the bitmap to be used by the bitmap brush.
if (SUCCEEDED(hr))
{
    hr = LoadResourceBitmap(
        m_pRenderTarget,
        m_pWICFactory,
        L"FERN",
        L"Image",
        &m_pBitmap
        );
}

若要建立點陣圖筆刷,請呼叫 ID2D1RenderTarget::CreateBitmapBrush 方法,並指定要繪製的 ID2D1Bitmap 。 方法會傳回 HRESULTID2D1BitmapBrush 物件。 某些 CreateBitmapBrush 多載可讓您藉由接受 D2D1_BRUSH_PROPERTIESD2D1_BITMAP_BRUSH_PROPERTIES 結構來指定其他選項。

if (SUCCEEDED(hr))
{
    hr = m_pRenderTarget->CreateBitmapBrush(
        m_pBitmap,
        &m_pBitmapBrush
        );
}

下一個範例會使用筆刷來填滿矩形。

m_pRenderTarget->FillRectangle(&rcBrushRect, m_pBitmapBrush);

設定擴充模式

有時候,漸層筆刷或點陣圖筆刷的漸層不會完全填滿所繪製的區域。

下圖顯示 ID2D1BitmapBrush的每個可能擴充模式組合的結果: D2D1_EXTEND_MODE_CLAMP (CLAMP) 、 D2D1_EXTEND_MODE_WRAP (WRAP) ,以及 D2D1_EXTEND_MIRROR (MIRROR) 。

原始影像和各種擴充模式所產生的影像圖例

下列範例示範如何將點陣圖筆刷的 x 和 y 擴充模式設定為 D2D1_EXTEND_MIRROR。 然後,它會使用 ID2D1BitmapBrush繪製矩形。

m_pBitmapBrush->SetExtendModeX(D2D1_EXTEND_MODE_MIRROR);
m_pBitmapBrush->SetExtendModeY(D2D1_EXTEND_MODE_MIRROR);

m_pRenderTarget->FillRectangle(exampleRectangle, m_pBitmapBrush);

它會產生輸出,如下圖所示。

在鏡像 X 方向和 Y 方向之後的原始影像和產生的影像圖例

轉換筆刷

當您使用筆刷繪製時,它會在轉譯目標的座標空間中繪製。 筆刷不會自動定位自己,使其與所繪製的物件對齊;根據預設,它們會開始在轉譯目標的原點 (0、0) 繪製。

您可以藉由設定其起點和終點,將 ID2D1LinearGradientBrush 定義的漸層「移動」至目的地區域。 同樣地,您可以藉由變更其中心與弧度來移動 ID2D1RadialGradientBrush 所定義的漸層。

若要將 ID2D1BitmapBrush 的內容對齊所繪製的區域,您可以使用 SetTransform 方法將點陣圖轉譯為所需的位置。 此轉換只會影響筆刷;它不會影響轉譯目標所繪製的任何其他內容。

下圖顯示使用 ID2D1BitmapBrush 填滿位於 (100, 100) 的矩形的效果。 左圖上的圖例顯示填滿矩形的結果,而不轉換筆刷:點陣圖是在轉譯目標的原點繪製。 因此,只有一部分的點陣圖會出現在矩形中。 右邊的圖例顯示轉換 ID2D1BitmapBrush 的結果,使其內容向右移位 50 圖元,並向下移 50 圖元。 點陣圖現在會填滿矩形。

使用點陣圖筆刷繪製的正方形圖例,而不轉換筆刷,以及轉換筆刷

下列程式碼示範如何完成此作業。 首先,將轉譯套用至 ID2D1BitmapBrush,將筆刷向右移動 50 圖元,沿著 X 軸往下移動 50 個圖元。 然後使用 ID2D1BitmapBrush 填滿左上角 (100、100) 和右下角的矩形, (200, 200) 。

// Create the bitmap to be used by the bitmap brush.
if (SUCCEEDED(hr))
{
    hr = LoadResourceBitmap(
        m_pRenderTarget,
        m_pWICFactory,
        L"FERN",
        L"Image",
        &m_pBitmap
        );
   
}

if (SUCCEEDED(hr))
{
    hr = m_pRenderTarget->CreateBitmapBrush(
        m_pBitmap,
        &m_pBitmapBrush
        );
}

D2D1_RECT_F rcTransformedBrushRect = D2D1::RectF(100, 100, 200, 200);

// Demonstrate the effect of transforming a bitmap brush.
m_pBitmapBrush->SetTransform(
     D2D1::Matrix3x2F::Translation(D2D1::SizeF(50,50))
     );

// To see the content of the rcTransformedBrushRect, comment
// out this statement.
m_pRenderTarget->FillRectangle(
     &rcTransformedBrushRect, 
     m_pBitmapBrush
     );

m_pRenderTarget->DrawRectangle(rcTransformedBrushRect, m_pBlackBrush, 1, NULL);