<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                ## 1.7 筆和刷 本節介紹 GDI+的兩類繪圖工具——筆和刷,它們與 GDI 的相比新增加了許多功能。 ### 1.7.1 筆 與 GDI 中的一樣,GDI+中的筆(pen)也是畫線狀圖的工具,但是功能更加強大。例 如:透明筆、圖案筆、自定義虛線風格、線帽、筆的縮放和旋轉、筆的連接點屬性等。 GDI+中的筆對應于 Pen 類,被定義在 GdiplusPen.h 頭文件中。 筆的構造方法主要有兩個: ``` Pen(const Color &color, REAL width = 1.0); // 單色筆 Pen(const Brush *brush, REAL width = 1.0); // 紋理圖案筆 ``` 其中,最常用的是第一個,它構造一個顏色為 color,寬度為 width(默認為 1)的單色筆。 如果顏色的α 值&lt;255,則所創建的筆就是帶透明度的筆。 (1)筆對齊 當筆寬大于 1 時,默認情況下,是以筆的中心與繪圖坐標對齊。但是,也可以采用 Pen類的方法: ``` Status SetAlignment(PenAlignment penAlignment); ``` 設置為內對齊,其輸入參數取枚舉類型 PenAlignment 的符號常量: ``` typedef enum { PenAlignmentCenter = 0, // 中心對齊(默認值) PenAlignmentInset = 1 // 內對齊 } PenAlignment; ``` 例如(輸出結果如圖 14-19 所示): ``` Graphics graph(pDC-&gt;m_hDC); Rect rect(20, 20, 300, 200); Pen pen(Color::Green, 30), redPen(Color::Red); graph.DrawEllipse(&pen, rect); graph.DrawRectangle(&redPen, rect); pen.SetAlignment(PenAlignmentInset); graph.TranslateTransform(340, 0); graph.DrawEllipse(&pen, rect); graph.DrawRectangle(&redPen, rect); ``` ![image](https://box.kancloud.cn/2016-04-18_57144a7ebf949.jpg) a) 中心對齊(默認值) b) 內對齊 圖 14-19 筆對齊 (2)圖案筆 筆類 Pen 的第二個構造方法,是從刷子來創建筆,如果是單色的實心刷,則相當于第一 個筆構造方法。如果刷子為條紋(影線)或紋理(圖像)等圖案刷,則該構造函數所創見的 就是對應的圖案筆。 例如(條紋筆畫橢圓,參見圖 14-20): ``` HatchBrush hBrush(HatchStyleCross, Color::Green, Color::Red); // 創建十字線條紋刷 Pen hPen(&**hBrush**, 40); // 創建寬度為 40 像素的條紋筆 graph.DrawEllipse(&hPen, 20, 20, 400, 250); // 畫橢圓 ``` ![image](https://box.kancloud.cn/2016-04-18_57144a7ed3842.jpg) 圖 14-20 條紋筆橢圓 ![image](https://box.kancloud.cn/2016-04-18_57144a7ee4817.jpg) 圖 14-21 紋理筆橢圓 又例如(紋理筆畫橢圓,參見圖 14-21): ``` Image img(L"張東健.bmp"); // 創建圖像對象,并裝入圖像文件 TextureBrush tBrush(&img); // 創建紋理刷 Pen tPen(&**tBrush**, 80); // 創建寬度為 80 像素的紋理筆 Graphics graph(GetDC()-&gt;m_hDC); // 創建圖形對象 graph.DrawEllipse(&tPen, 40, 40, 640, 400); // 畫橢圓 ``` (3)線型 與 GDI 一樣,對 GDI+中的筆,也可以設置線型。所用的方法為: ``` Status SetDashStyle(DashStyle dashStyle); ``` 其中的輸入參數,為虛線風格枚舉 DashStyle:(GdiplusEnums.h) ``` enum DashStyle { DashStyleSolid, // 0 實線 (默認值) DashStyleDash, // 1 虛線 DashStyleDot, // 2 點線: DashStyleDashDot, // 3 虛點線: DashStyleDashDotDot, // 4 虛點點線 DashStyleCustom // 5 自定義虛線 }; ``` ![](https://box.kancloud.cn/2016-04-18_57144a7f0a7b3.png) 可以用 Pen 類的另一個方法來獲取筆的線型: ``` DashStyle GetDashStyle() const; ``` GDI+中的線型,大多數與 GDI 中的相同,區別主要有兩點: + GDI 中的非實線線型,對寬度&gt;1 的筆無效;而 GDI+的筆對任意非零寬度的筆都是有效的。 + GDI+中新增了一種風格——自定義虛線風格。 具體的自定義虛線風格,由 Pen 類的設置虛線圖案的方法 ``` Status SetDashPattern(const REAL *dashArray, INT count); ``` 來設置,其中的實數數組 dashArray 含若干個正實數(單位為像素),按線、空、線、空、?? 的交叉方式排列;參數 count 為數組中實數的個數(須&gt;0)。 例如(參見圖 14-22): ``` Graphics graph(pDC->m_hDC); Pen pen(Color::Black, 8); // 創建寬 8 個像素的黑色筆(畫虛線用) // 線 5、空 2、線 15、空 4(像素) REAL dashVals[4] = {5.0f, 2.0f, 15.0f, 4.0f}; FontFamily fontFamily(L"Times New Roman"); // 創建字體族對象 // 創建 5 號字大小的 Times New Roman 字體 Font font(&fontFamily, 10.5); // 創建綠色的實心刷(寫字符串用) SolidBrush brush(Color(0, 128, 0)); // 筆的虛線風格枚舉常量的名稱字符串數組 CString strs[] = {L"DashStyleSolid", L"DashStyleDash", L"DashStyleDot", L"DashStyleDashDot", L"DashStyleDashDotDot", L"DashStyleCustom"}; for (int i = 0; i &lt;= 5; i++) { // 繪制各種風格的虛線及其名稱串 pen.**SetDashStyle**((DashStyle)i); // 設置筆的虛線風格 // 設置自定義虛線圖案 if (i == 5) pen.SetDashPattern(dashVals, 4); // 畫虛線 graph.DrawLine(&pen, 10, 10 + i * 20, 400, 10 + i * 20); // 繪制虛線風格枚舉常量名稱字符串 graph.DrawString(strs[i], -1, &font, PointF(410, 2 + i * 20), &brush); } ``` ![image](https://box.kancloud.cn/2016-04-18_57144a7f22f0b.jpg) 圖 14-22 虛線風格 還可以用 Pen 類的另一個方法來獲取筆的自定義虛線圖案數據: ``` INT GetDashPatternCount(VOID); // 獲取虛線數組中實數的個數 Status GetDashPattern(REAL *dashArray, INT count); // 獲取虛線數組 ``` (4)線帽 線帽(line cap)是指線條兩端的外觀,默認為正方形,也可以用 Pen 類的下列方法來 設置不同的線端形狀: ``` Status SetStartCap(LineCap startCap); // 設置起點的線帽 Status SetEndCap(LineCap endCap); // 設置終點的線帽 // 設置起點、終點和虛線的線帽 Status SetLineCap(LineCap startCap, LineCap endCap, DashCap dashCap); ``` 其中的線帽枚舉 LineCap 為(GdiplusEnums.h): ``` typedef enum { LineCapFlat = 0, // 平線,直線起點位于平線的中點(默認值) LineCapSquare = 1, // 方形,高度=線寬,直線起點位于正方形中心 LineCapRound = 2, // 圓形,直徑=線寬,直線起點位于圓心 LineCapTriangle = 3, // 三角,高度=線寬,直線起點位于其底邊中點 LineCapNoAnchor = 0x10, // 無錨,同平線 LineCapSquareAnchor = 0x11, // 方形錨,高度&gt;線寬,直線起點位于正方形中心 LineCapRoundAnchor = 0x12, // 圓形錨,直徑&gt;線寬,直線起點位于圓心 LineCapDiamondAnchor = 0x13, // 菱形錨,高度&gt;線寬,直線起點位于菱形中心 LineCapArrowAnchor = 0x14, // 箭頭錨,高度&gt;線寬,直線起點位于箭頭的尖點 LineCapCustom = 0xff // 自定義線帽 } LineCap; ``` 自定義線帽,需要用到 GDI+專門為此定義的類 CustomLineCap。其構造函數為: ``` CustomLineCap(const GraphicsPath *fillPath, const GraphicsPath *strokePath, LineCap baseCap, REAL baseInset); ``` 其中要用到圖形路徑類 GraphicsPath,該類中有圖形各種添加圖形方法,只是把 Graphics 類 繪圖方法名中的 Draw 改成 Add 即可。例如:AddLine、AddRectangle 和 AddPolygon 等。使 用時,可以先創建一個空路徑,然后調用這些添加圖形方法若干次,就可以生成路徑了。 ![image](https://box.kancloud.cn/2016-04-18_57144a7f36e43.jpg) 例如(各類線帽,參見圖 14-23 和圖 14-24): ![image](https://box.kancloud.cn/2016-04-18_57144a7f484f5.jpg) 箭頭線帽 構造箭頭線帽頭尾所使用的坐標系 圖 14-23 自定義線帽 ``` // 自定義箭頭線帽 GraphicsPath startPath, endPath; // 創建起點和終點路徑對象 startPath.AddRectangle(Rect(-10, -5, 20, 10)); // 起點矩形 Point polygonPoints[4] = {Point(0, -20), Point(10, 0), Point(0, -10), Point(-10, 0)}; endPath.AddPolygon(polygonPoints, 4); // 終點箭頭 CustomLineCap startCap(NULL, &startPath); // 創建起點線帽 CustomLineCap endCap(NULL, &endPath); // 創建終點線帽 // 定義筆 Pen pen(Color::Black, 20); // 畫帶線帽粗線的黑筆 Pen redPen(Color::Red); // 畫不帶線帽細線的紅筆 // 中英文線帽字符串數組 CString cstrs[] = {L"平線帽", L"方線帽", L"圓線帽", L"三角線帽", L"無錨線帽", L"方錨線帽", L"圓錨線帽", L"菱錨線帽", L"箭錨線帽", L"定制線帽"}; CString estrs[] = {L"LineCapFlat", L"LineCapSquare", L"LineCapRound", L"LineCapTriangle", L"LineCapNoAnchor", L"LineCapSquareAnchor", L"LineCapRoundAnchor", L"LineCapDiamondAnchor", L"LineCapArrowAnchor", L"LineCapCustom"}; // 創建字體 FontFamily fontFamily(L"Times New Roman"); // 對應中文的"宋體" Font font(&fontFamily, 10.5); // 五號字 // 繪制各種線帽 Graphics graph(pDC-&gt;m_hDC); for (int i = 0; i &lt;= 9; i++) { // 畫線循環 LineCap lc = (LineCap)(i &lt; 4 ? i : i + 12); // 線帽常量(整數) if(i &lt; 9) pen.SetLineCap(lc, lc, DashCapFlat); // 標準線帽 else { // 自定義線帽(i = 9) pen.SetCustomStartCap(&startCap); // 設置自定義的起點線帽 pen.SetCustomEndCap(&endCap); // 設置自定義的終點線帽 pen.SetWidth(3.0f); // 重新設置線寬為 3 個像素 } int y = 20 + i * 40; // 計算直線的垂直坐標 graph.DrawLine(&pen, 100, y, 400, y); // 畫帶線帽的粗線 graph.DrawLine(&redPen, 100, y, 400, y); // 畫不帶線帽的細線 // 繪制中英文線帽字符串 graph.DrawString(cstrs[i], -1, &font, PointF(15.0f, y - 8.0f), &brush); graph.DrawString(estrs[i], -1, &font, PointF(425.0f, y - 8.0f), &brush); } ``` ![image](https://box.kancloud.cn/2016-04-18_57144a7f59b36.png) 圖 14-24 線帽的種類 圖 14-25 箭頭線帽的旋轉直線簇 又例如(旋轉箭頭線帽,參見圖 14-25): ``` // startCap 和 endCap 的創建同上例,需包含頭文件 &lt;math.h&gt; Pen pen(Color::DarkGreen, 2); pen.SetCustomStartCap(&startCap); pen.SetCustomEndCap(&endCap); double radian = 3.14159265358979323846 / 180.0; for (int i = 0; i &lt; 360; i += 10) graph.DrawLine(&pen, 220, 220, 220 + (INT) (200 * cos(i * radian)), 220 + (INT) (200 * sin(i * radian))); ``` 方法 SetLineCap 的最后一個輸入參數 DashCap dashCap,用于設置虛線內部各線段端點 的形狀。其取值是枚舉類型(GdiplusEnums.h): ``` typedef enum { DashCapFlat = 0, // 平線(默認值) DashCapRound = 2, // 圓形 DashCapTriangle = 3 // 三角 } DashCap; ``` 可見,只有三種選擇:平、圓和三角。之所以枚舉常量所對應的值不連續,是因為要同 LineCap 枚舉的對應常量一致。 注意,虛線帽的設置,只影響其虛線內部的線段,不會影響整條虛線的頭尾形狀,它們 是由 SetLineCap 方法的前兩個參數來分別設置的。例如(參見圖 14-26): ``` Graphics graph(pDC-&gt;m_hDC); Pen pen(Color::Black, 10); pen.SetLineCap(LineCapFlat, LineCapFlat, **DashCapFlat**); //pen.SetLineCap(LineCapFlat, LineCapFlat, **DashCapRound**); //pen.SetLineCap(LineCapFlat, LineCapFlat, **DashCapTriangle**); REAL dashVals[4] = {5.0f, 2.0f, 15.0f, 4.0f}; for (int i = 0; i &lt;= 5; i++) { pen.SetDashStyle((DashStyle)i); if (i == 5) pen.SetDashPattern(dashVals, 4); graph.DrawLine(&pen, 10, 10 + i * 20, 400, 10 + i * 20); } ``` ![image](https://box.kancloud.cn/2016-04-18_57144a7f74de2.jpg) DashCapRound 圓虛線帽 ![image](https://box.kancloud.cn/2016-04-18_57144a862cedc.jpg) DashCapFlat 平虛線帽 ![image](https://box.kancloud.cn/2016-04-18_57144a863fdbe.jpg) DashCapTriangle 三角虛線帽 圖 14-26 虛線帽 (5)線連接 筆的線連接(join)屬性,也是 GDI+新增的功能。可以使用 Pen 類的方法: ``` Status SetLineJoin( LineJoin lineJoin); ``` 來設置筆的線連接屬性。其中輸入參數為枚舉類型 LineJoin: ``` enum LineJoin { LineJoinMiter = 0, // 斜接(默認值) LineJoinBevel = 1, // 斜截 LineJoinRound = 2, // 圓角 LineJoinMiterClipped = 3 // 斜剪 }; ``` 例如(參見圖 14-27): ``` Graphics graph(pDC-&gt;m_hDC); Pen pen(Color::DarkGreen, 40); for (int i = 0; i &lt; 4; i++) { pen.SetLineJoin((LineJoin)i); graph.DrawRectangle(&pen, 40 + i * 150, 40, 100, 100); } ``` ![image](https://box.kancloud.cn/2016-04-18_57144a8652641.jpg) LineJoinMiter LineJoinBevel LineJoinRound LineJoinMiterClipped 斜接 斜截 圓角 斜剪 圖 14-27 線連接 從該例還看不出斜剪與斜接有什么區別,因為斜剪 LineJoinMiterClipped 主要針對交角 很小,相交部分很長的情形。在斜剪線連接方式下,可以調用 Pen 類的方法 ``` Status SetMiterLimit(REAL miterLimit); ``` 來設置相交部分的最大限制長度,默認是 10.0(相對于線寬的比值)。 對 LineJoinMiterClipped 方式的線連接,如果 miterLimit &lt; 相交部分的長度,則會截斷 至線頭(同斜截方式,相當于 miterLimit = 1.0);如果 miterLimit &gt;= 相交部分的長度,則繪 制完整的相交部分。 但是對 LineJoinMiter 方式的線連接,如果 miterLimit &lt; 相交部分的長度,則會截斷至 miterLimit 所指定比例的長度;如果 miterLimit &gt;= 相交部分的長度,則繪制完整的相交部分。 例如(參見圖 14-28): ``` Graphics graph(pDC-&gt;m_hDC); Pen redPen(Color::Red); // 畫細線的紅筆 Pen pen(Color::DarkGreen, 40.0f); // 畫粗線的綠色筆 Point points[] = {Point(20, 100), Point(400, 130), Point(20, 160)}; // 點數組 pen.SetLineJoin(LineJoinMiter); // 斜接 //pen.SetLineJoin(LineJoinBevel); // 斜截 //pen.SetLineJoin(LineJoinRound); // 圓角 //pen.SetLineJoin(LineJoinMiterClipped); // 斜剪 //pen.SetMiterLimit(20.0f); // 設置斜接限長 graph.DrawLines(&pen, points, 3); // 畫粗線 graph.DrawLines(&redPen, points, 3); // 畫細線 ``` ![image](https://box.kancloud.cn/2016-04-18_57144a8664e83.png) 圖 14-28 小交角線連接 圖 14-29 不同斜接限長下的斜接線連接 如果不斷修改斜接線連接 LineJoinMiter 方式下的線長限制(0.0f~13.0f),則可得到不同 截斷長度的斜交角。例如(參見圖 14-29): ``` pen.SetLineJoin(LineJoinMiter); // 斜接 pen.SetMiterLimit(1.0f/*~13.0f*/); // 設置斜接限長 ``` ### 1.7.2 刷 與 GDI 中的一樣,GDI+中的刷(brush)也是畫填充圖的工具,GDI+中也有與 GDI 相 對應的實心刷(單色刷)、條紋刷(影線刷)和紋理刷(圖像刷)。不過,GDI+又新增加了 功能強大的線性漸變刷和路徑漸變刷,而且還為所有這些刷各自建立了對應的類,基類是Brush(功能少)。 ![image](img/Image_046.png) 圖 14-30 是 GDI+中各種刷類的層次結構圖, 所有刷類都被定義在頭文件 Gdiplus Brush.h 中。 (1)刷基類 Brush ![](https://box.kancloud.cn/2016-04-18_57144a86872e1.png) Brush 是所有 GDI+具體刷類的基類,Brush 類沒有自己的公用構造函數,屬于非實例化 類(用戶不能創建 Brush 類的對象和實例),只是定義了三個公用的方法(接口): ``` Brush *Clone( VOID) const; // 克隆,用于復制 Brush 及其派生類對象 Status GetLastStatus(VOID); // 獲取最后狀態,返回刷對象最近的錯誤狀態 BrushType GetType(VOID); // 獲取類型,返回當前(派生)刷的類型枚舉常量 ``` 下面是 BrushType 枚舉類型的定義(GdiplusEnums.h): ``` typedef enum { BrushTypeSolidColor = 0, // 實心單色刷 BrushTypeHatchFill = 1, // 影線條紋填充刷 BrushTypeTextureFill = 2, // 圖像紋理填充刷 BrushTypePathGradient = 3, // 路徑漸變刷 BrushTypeLinearGradient = 4 // 線性漸變刷 } BrushType; ``` (2)實心刷類 SolidBrush GDI+中,實心的單色刷對應于 SolidBrush 類,它只有一個構造函數: ``` SolidBrush(const Color &color); ``` 輸入參數為顏色對象的引用。 在前面的例子中已經多次使用了 SolidBrush 類,下面再舉一個畫正葉曲線的例子,下面 是正葉曲線的極坐標方程及其到直角坐標系的轉換公式: ![image](https://box.kancloud.cn/2016-04-18_57144a869d816.png) 其中,l 為葉片長度、n 為葉片數目。 因為 GDI+并沒有畫正葉曲線的專門函數,所以需要用多邊形、樣條曲線或圖形路徑來 刻畫它。可以使用填充多邊形、填充封閉曲線和填充圖形路徑等方式來進行繪制,下面的代碼使用的是填充閉基樣條曲線,輸出結果如圖 14-31 所示。 + 繪制單個正葉曲線的函數代碼: ``` #include <math.h> void DrawLeaves(Graphics &graph, const Color col, Point &O, int l, int n) { double radian = 3.14159265358979323846 / 180.0; int m = n < 5 ? 21 : 11; int N = m * n; double da = 360.0 / N; PointF *ps = new PointF[N]; for (int i = 0; i &lt; N; i++) { double r = abs(l * cos(radian * (n * i * da)/ 2.0)), x = r * cos(i * da * radian), y = r * sin(i * da * radian); ps[i].X = REAL(O.X + x); ps[i].Y = REAL(O.Y + y); } graph.FillClosedCurve(&SolidBrush(col), ps, N); } ``` + 繪制系列彩色正葉曲線的調用序列: ``` Graphics graph(pDC-&gt;m_hDC); Color cols[] = {Color::Aqua, Color::Aquamarine, Color::DarkBlue, Color::DarkKhaki, Color::DeepPink, Color::BlueViolet, Color::Brown, Color::BurlyWood, Color::CadetBlue, Color::Chartreuse, Color::Turquoise, Color::Coral, Color::CornflowerBlue, Color::Crimson, Color::DarkCyan}; bool color = true; // false; for (int i = 0; i &lt; 15; i++) DrawLeaves(graph, color ? cols[i] : Color::Green, Point(100 + 200* (i % 5), 100 + 200 * (i / 5)), 100, i + 1); ``` ![image](https://box.kancloud.cn/2016-04-18_57144a86af13d.jpg) 圖 14-31 彩色正葉曲線系列 (3)條紋刷類 HatchBrush 條紋是一種重復填充的小方形圖案,一般為橫線、豎線、斜線和小方塊等構成。GDI+ 中,條紋刷(hatch brush 影線刷/陰影刷)對應于 HatchBrush 類,它也只有一個構造函數: ``` HatchBrush(HatchStyle hatchStyle, const Color &foreColor, const Color &backColor = Color()); ``` 其中:第一個參數為條紋類型,第二個參數為前景色(條紋色),第三個參數為背景色(空隙色)。 GDI+中一共有 53 種條紋風格,而 GDI 中只有前 6 種。條紋風格枚舉 HatchStyle 也被定 義在頭文件 GdiplusEnums.h 中: ``` enum HatchStyle { HatchStyleHor izontal, // 0:橫線 HatchStyleVertical, // 1:豎線 HatchStyleForwardDiagonal, // 2:正斜線 HatchStyleBackwardDiagonal, // 3:反斜線 HatchStyleCross, // 4:十字線 HatchStyleDiagonalCross, // 5:斜十字線 HatchStyle05Percent, // 6:5% HatchStyle10Percent, // 7:10% ... HatchStyleSphere, // 47:球面 HatchStyleSmallGrid, // 48:小網格 HatchStyleSmallChecker Board, // 49:小跳棋盤 HatchStyleLargeCheckerBoard, // 50:大跳棋盤 HatchStyleOutlinedDiamond, // 51:斜綱線 HatchStyleSolidDiamond, // 52:實菱形 HatchStyleTotal, // = 53(0 ~ 52):條紋風格總數 HatchStyleLargeGrid = HatchStyleCross, // 4:大網格 HatchStyleMin = HatchStyleHorizontal, // 0:條紋風格最小值 HatchStyleMax = HatchStyleTotal - 1, // 52:條紋風格最大值 }; ``` 例如(參見圖 14-32): ``` Graphics graph(pDC-&gt;m_hDC); Pen pen(Color::Black); SolidBrush textBrush(Color::Red); FontFamily fontFamily(L"Times New Roman"); Font font(&fontFamily, 18); CString str; StringFormat sfmt; // 文本格式 sfmt.SetAlignment(StringAlignmentCenter); // 水平對齊 sfmt.SetLineAlignment(StringAlignmentCenter); // 垂直對齊 int w = 50, h = 50, s = 5; for (int i = 0; i &lt; 53; i++) { // 主循環 HatchBrush brush(HatchStyle(i), Color::Black, Color::White); RectF rect(REAL(s + (i % 10) * (w + s)), REAL(s + (i / 10) * (h + s)), REAL(w), REAL(h)); graph.FillRectangle(&brush, rect); // 畫條紋塊 str.Format(L"%d", i); // 繪制數字編號的文本串: graph.DrawString(str, str.GetLength(), &font, rect, &sfmt, &textBrush); } ``` ![image](https://box.kancloud.cn/2016-04-18_57144a86ca8cc.jpg) 圖 14-32 條紋刷的條紋風格 與 GDI 一樣,在 GDI+中也可以調整條紋刷和圖像刷的起點。這需要使用圖像類 Graphics 的方法 SetRenderingOrigin 來設置渲染原點為(x, y)(默認為(0, 0)): ``` Status SetRenderingOrigin(INT x, INT y); ``` (4)紋理刷類 TextureBrush 紋理刷(texture brush)就是圖像刷,它將刷中所裝入的圖像,在目標區域中進行平鋪, 可達到紋理效果。GDI 中也有圖像刷,但僅限于使用位圖資源和(非常費事才能使用)BMP 文件。在 GDI+中,紋理刷所對應的是 TextureBrush 類,它有 7 個構造函數,最常用的為: ``` TextureBrush(Image* image, WrapMode wrapMode = WrapModeTile); ``` 其中,第一個參數是圖像對象的指針,第二個參數是排列方式的枚舉常量(GdiplusEnums.h): ``` typedef enum { WrapModeTile = 0, // 平鋪(瓦)(默認值) WrapModeTileFlipX = 1, // 平鋪且 X 向翻轉(相鄰列左右翻轉) WrapModeTileFlipY = 2, // 平鋪且 Y 向翻轉(相鄰行上下翻轉) WrapModeTileFlipXY = 3, // 平鋪且 XY 向翻轉(相鄰行列左右上下翻轉) WrapModeClamp = 4 // 不平鋪(不重復,夾住) } WrapMode; ``` 還可以用紋理刷類的下面兩個方法來設置和獲取刷的排列方式: ``` Status SetWrapMode(WrapMode wrapMode); WrapMode GetWrapMode() const; ``` 例如(參見圖 14-33): ``` Graphics graph(pDC-&gt;m_hDC); Image img(L"張東健.bmp"); TextureBrush brush(&img, WrapModeTile/*FlipXY*/); //TextureBrush brush(&img, **WrapModeClamp**); RECT rect; GetClientRect(&rect); graph.FillRectangle(&brush, RectF(0.0f, 0.0f, REAL(rect.right), REAL(rect.bottom))); ``` ![image](https://box.kancloud.cn/2016-04-18_57144a86e3cd0.jpg) 平鋪(WrapModeTile) ![image](https://box.kancloud.cn/2016-04-18_57144a87026c9.jpg) 平鋪且 X 向翻轉(WrapModeTileFlipX) ![image](https://box.kancloud.cn/2016-04-18_57144a871549b.jpg) 平鋪且 Y 向翻轉(WrapModeTileFlipY) ![image](https://box.kancloud.cn/2016-04-18_57144a872bafc.jpg) 平鋪且 XY 向翻轉(WrapModeTileFlipXY) ![image](https://box.kancloud.cn/2016-04-18_57144a8743fc4.jpg) 不平鋪(WrapModeClamp) 圖 14-33 紋理刷排列方式 紋理刷類 TextureBrush 中,還有幾個方法,可以對刷中的圖像進行平移(translate)、旋 轉(rotate)和縮放(scale)等變換(transform)(這是 GDI 里所沒有的功能): ``` Status TranslateTransform(REAL dx, REAL dy, MatrixOrder order = MatrixOrderPrepend); Status RotateTransform(REAL angle, MatrixOrder order = MatrixOrderPrepend) ; Status ScaleTransform(REAL sx, REAL sy, MatrixOrder order = MatrixOrderPrepend); ``` 例如(參見圖 14-34): ``` Graphics graph(pDC-&gt;m_hDC); Image img(L"張東健.bmp"); TextureBrush brush(&img); //brush.TranslateTransform(30, 30); // 平移(30, 30) brush.RotateTransform(30); // 旋轉 30 度 //brush.ScaleTransform(3, 1); // 水平放大 3 倍 //brush.ScaleTransform(1, 3); // 垂直放大 3 倍 RECT rect; GetClientRect(&rect); graph.FillRectangle(&brush, RectF(0.0f, 0.0f, REAL(rect.right), REAL(rect.bottom))); ``` ![image](https://box.kancloud.cn/2016-04-18_57144a875921f.jpg) 平移(30, 30) ![image](https://box.kancloud.cn/2016-04-18_57144a876daf7.jpg) 旋轉 30 度 ![image](https://box.kancloud.cn/2016-04-18_57144a87814c3.jpg) 水平放大 3 倍 ![image](https://box.kancloud.cn/2016-04-18_57144a8795582.jpg) 垂直放大 3 倍 圖 14-34 紋理刷變換 (5)線性漸變刷類 LinearGradientBrush 線性漸變刷(linear gradient brush 線性梯度刷)使用逐漸變化的顏色填充目標區域。是 GDI+新增的功能。線性漸變刷所對應的類為 LinearGradientBrush,它有 6 個構造函數,前 3 個是整數版,后 3 個是對應的浮點數版。下面是 3 個整數版的構造函數: ``` LinearGradientBrush(const Point& point1, const Point& point2, const Color& color1, const Color& color2); LinearGradientBrush(const Rect& rec t, const Color& color1, const Color& color2, LinearGradientMode mode); LinearGradientBrush(const Rect& rect, const Color& color1, const Color& color2, REAL angle, BOOL is AngleScalable = FALSE); ``` 在這三種構造函數中,第一個是點到點、第二個是矩形與漸變模式、第三個是是矩形與旋轉角度。限于篇幅,這里只介紹其中點到點的整數版構造函數的具體使用方法。 1)點到點漸變 點到點的漸變是指刷子所填充的顏色,沿著點 point1 到點 point2 的直線,從顏色 color1 連續變化到 color2。若 p1 和 p2 點的 y 值相等,則為水平方向的漸變;若 p1 和 p2 點的 x 值 相等,則為垂直方向的漸變;p1 和 p2 點的 x 和 y 值都不相等,則為斜對角方向的漸變。 例如(參見圖 14-35): ``` Graphics graph(pDC->m_hDC); Point p1(10, 10), p2(110, 10), p3(10, 110), p4(230, 10), p5(330, 110); Size size(100, 100); Color col1(255, 0, 0), col2(0, 0, 255); LinearGradientBrush hbrush(p1, p2, col1, col2); graph.FillRectangle(&hbrush, Rect(p1, size)); LinearGradientBrush vbrush(p1, p3, col1, col2); graph.FillRectangle(&vbrush, Rect(Point(120, 10), size)); LinearGradientBrush dbrush(p4, p5, col1, col2); graph.FillRectangle(&dbrush, Rect(Point(230, 10), size)); ``` ![image](https://box.kancloud.cn/2016-04-18_57144a87aa1bf.jpg) 水平漸變 垂直漸變 對角漸變 圖 14-35 線性漸變刷 其實,線性漸變刷默認是按 WrapModeTile 平鋪方式重復排列的(原點是 point1),例如(參見圖 14-36 a)): ``` Graphics graph(pDC-&gt;m_hDC); Point p1(10, 10), p2(110, 10), p3(10, 110); Color col1(255, 0, 0), col2(0, 0, 255); LinearGradientBrush hbrush(p1, p2, col1, col2); //hbrush.SetWrapMode(WrapModeTileFlipX); graph.FillRectangle(&hbrush, Rect(p1, Size(400, 200))); LinearGradientBrush vbrush(p1, p3, col1, col2); //vbrush.SetWrapMode(WrapModeTileFlipX); graph.FillRectangle(&vbrush, Rect(Point(420, 10), Size(200, 410))); LinearGradientBrush dbrush(p1, Point(110, 100), col1, col2); //dbrush.SetWrapMode(WrapModeTileFlipX); graph.FillRectangle(&dbrush, Rect(Point(10, 220), Size(400, 200))); ``` 你也可以將上面代碼中的注釋符“//”去掉,利用線性漸變刷類的方法 ``` Status SetWrapMode(WrapMode wrapMode); ``` 來設置畫刷的排列方式為 WrapModeTileFlipX 平鋪并水平翻轉,參見圖 14-36 b)。 ![image](https://box.kancloud.cn/2016-04-18_57144a87bb582.jpg) 圖 14-37 參數的含義 ![image](https://box.kancloud.cn/2016-04-18_57144a87cf56d.jpg) a) 平鋪重復排列 b) 加水平翻轉 圖 14-36 按平鋪重復排列的線性漸變刷 下面是一個利用水平線性漸變刷來畫陰陽八卦中的陰陽魚例子(參見圖 14-37 和圖 14-38): ``` LinearGradientBrush R2BBrush(Point(0, 10), Point(200, 10), Color(255, 0, 0), Color(0, 0, 255)); LinearGradientBrush B2YBrush(Point(0, 10), Point(200, 10), Color(0, 0, 255), Color(255, 255, 0)); Pen bluePen(Color(255, 0, 0, 255)); Rect circleRect(0, 0, 200, 200); Rect leftRect(0, 50, 100, 100); Rect rightRect(100, 50, 100, 100); Graphics graph(pDC-&gt;m_hDC); graph.FillPie(&R2BBrush, circleRect, 0.0f, 180.0f); graph.FillPie(&B2YBrush, circleRect, 180.0f, 180.0f); graph.FillPie(&R2BBrush, leftRect, 180.0f, 180.0f); graph.FillPie(&B2YBrush, rightRect, 0.0f, 180.0f); int r = 10; graph.FillEllipse(&SolidBrush(Color(0, 255, 0)), 50 - r, 100 - r, 2 * r, 2 * r); graph.FillEllipse(&SolidBrush(Color(255, 0, 255)), 150 - r, 100 - r, 2 * r, 2 * r); ``` ![image](https://box.kancloud.cn/2016-04-18_57144a87e145b.jpg) ![image](https://box.kancloud.cn/2016-04-18_57144a87f367d.jpg) ![image](https://box.kancloud.cn/2016-04-18_57144a881028e.png) ![image](https://box.kancloud.cn/2016-04-18_57144a882e374.jpg) 圖 14-38 繪制陰陽魚的分步輸出結果 2)多色漸變 線性漸變刷還有很多其他功能,例如可利用刷的方法: ``` Status SetInterpolationColors(const Color *presetColors, const REAL *blendPositions, INT count); ``` 來設置多色漸變。其中,presetColors 為多色數組、blendPositions 為以百分比表示的對應混色點的位置(首、尾值必須為 0.0f 和 1.0f,中間的值應該按遞增序排列)、count 為顏色和混 色點位的數目。例如(參見圖 14-39): ``` Color cols[] = {Color::Red, Color::Orange, Color::Yellow, Color::Green, Color::Cyan, Color::Blue, Color::Purple, Color::Magenta}; REAL bps[] = {0.0f, 0.15f, 0.3f, 0.45f, 0.6f, 0.75f, 0.875f, 1.0f}; LinearGradientBrush brush(Point(10, 10), Point(810, 10), Color::Black, Color::White); brush.SetInterpolationColors(cols, bps, 8); graph.FillRectangle(&brush, Rect(10, 10, 800, 100)); ``` ![image](https://box.kancloud.cn/2016-04-18_57144a88405e8.jpg) 圖 14-39 多色漸變 另外,也可以像紋理刷和條紋刷一樣,設置線性漸變刷的渲染原點等。 路徑漸變刷的內容,安排到下一章的第 15.1.2 小節中,在介紹過路徑的基本概念和使用方法之后再來講解。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看