<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>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                ## 1.6 圖形類 Graphics 與 GDI 的 MFC 類 CDC 類似,GDI+的繪圖功能主要由圖形類 Graphics 承擔。 圖形類 Graphics 是 GDI+的核心,它提供繪制圖形、圖像和文本的各種方法(似 GDI 中的 CDC 類),還可以存儲顯示設備和被畫項目的屬性(到圖元文件)。Graphics 類及其方 法都被定義在頭文件 Gdiplusgraphics.h 中。 ![image](https://box.kancloud.cn/2016-04-18_57144a7e15a2e.jpg) ![image](https://box.kancloud.cn/2016-04-18_57144a7e3300b.jpg) 圖 14-12 顏色枚舉常量 ### 1.6.1 構造函數 Graphics 類的構造函數有如下 4 種: ``` Graphics(Image* image); // 用于繪制圖像 Graphics(HDC hdc); // 用于在當前窗口中繪圖 Graphics(HDC hdc, HANDLE hdevice); // 用于在制定設備上繪制圖形 Graphics(HWND hwnd, BOOL icm = FALSE); // 用于在指定窗口中繪圖 ``` 其中,最常用的是第二種——在當前視圖窗口中繪圖的圖形類構造函數。 注意,該構造函數的輸入參數,是設備上下文的句柄,而不是 CDC 類對象的指針。一 般可以由 CDC 對象得到(因 CDC 類含有公用數據成員 HDC m_hDC;): + 在 OnDraw 函數中,利用輸入參數 CDC *pDC,就可直接得到 DC 句柄。例如: ``` Graphics graph(pDC-&gt;m_hDC); ``` + 在視圖類的其他函數中,可先利用 GetDC 函數得到 CDC 指針,然后再利用它去獲 取 DC 的句柄。例如: ``` Graphics graph(GetDC()-&gt;m_hDC); ``` 也可以使用 Graphics 類的另一個構造函數 `Graphics(HWND hwnd, BOOL icm = FALSE);`,利用視圖類的窗口句柄成員來構造 Graphics 對象。例如: ``` Graphics graph(this-&gt;m_hWnd); ``` ### 1.6.2 狀態枚舉 status 在圖形類 Graphics 中,封裝了各種繪圖方法。每種繪圖方法被調用后,都會返回一種 叫做 status 的枚舉值,反映該方法是否被正確執行,0 表示正確,其他大于 0 的值為錯誤代 碼(GdiplusTypes.h): ``` typedef enum { // 狀態枚舉(含 22 個枚舉值) Ok = 0, GenericError = 1, InvalidParameter = 2, OutOfMemory = 3, ... PropertyNotSupported = 20, ProfileNotFound = 21 } Status; ``` GDI+的繪圖功能被封裝在圖形類 Graphics 中,下面介紹其中的常用繪圖方法。先講繪 制線型圖的方法,再講繪制填充圖的方法,最后講繪制文字的方法。 ### 1.6.3 畫線型圖的方法 GDI+中繪制線型圖形的方法與 GDI 的類似,也包括繪直線、矩形、橢圓和多邊形等, 但是 GDI+增加了浮點版本和若干新功能。GDI+的畫線函數都是 Graphics 類的方法,而且所 有方法的名稱都是以 Draw 開頭。 (1)畫直線[折線]DrawLine[s] 在 GDI+中定義了 6 種繪制直線和折線的方法,前三個為整數版,后三個為對應的浮點 數版: ``` Status DrawLine(const Pen* pen, INT x1, INT y1, INT x2, INT y2); Status DrawLine(const Pen* pen, const Point& pt1, const Point& pt2); Status DrawLines(const Pen* pen, const Point* points, INT count); Status DrawLine(const Pen* pen, REAL x1, REAL y1, REAL x2, REAL y2); Status DrawLine(const Pen* pen, const PointF& pt1, const PointF& pt2); Status DrawLines(const Pen* pen, const PointF* points, INT count); ``` 其中: + DrawLine——畫直線(4 個重載),參數 pen 為畫直線所用的筆、(x1, y1)和 pt1 為 直線的起點、(x2, y2)和 pt2 為直線的終點。GDI 的相應函數為 MoveTo 和 LineTo。 + DrawLines——畫折線(一串相互連接的直線段)(2 個重載),參數 points 為點數 組、count 為數組中點的數目。GDI 的相應函數為 Polyline。 (2)畫矩形[組] DrawRectangle[s] 在 GDI+中也定義了 6 種繪制矩形和矩形組的方法,也是前三個為整數版,后三個為對 應的浮點數版: ``` Status DrawRectangle(const Pen* pen, const Rect& rect); Status DrawRectangle(const Pen* pen, INT x, INT y, INT width, INT height); Status DrawRectangles(const Pen* pen, const Rect* rects, INT count); Status DrawRectangle(const Pen* pen, const RectF& rect); Status DrawRectangle(const Pen* pen, REAL x, REAL y, REAL width, REAL height); Status DrawRectangles(const Pen* pen, const RectF* rects, INT count); ``` 其中: + DrawRectangle——畫單個矩形(4 個重載),參數 pen 為畫矩形所用的筆、rect 為 矩形區域、(x, y)為矩形的左上角、(width, height)為矩形的大小(寬,高)。與 GDI 的對應函數 BOOL Rectangle( int x1, int y1, int x2, int y2);的區別主要是 GDI+的第 2 個和第 4 個畫矩形方法的后兩個輸入參數,不再是 GDI 中的矩形右下角的坐標, 而改成矩形的寬和高了。 + DrawRectangles——畫多個矩形(2 個重載),參數 rects 為矩形數組、count 為數組 中矩形的數目。GDI 中沒有同時繪制一個矩形數組的函數。 (3)[橢]圓 DrawEllipse GDI+中有 4 個重載的繪制橢圓的方法,如果輸入參數所確定的外接矩形的寬高相等, 則畫圓。也是前兩個為整數版,后兩個為對應的浮點數版: ``` Status DrawEllipse(const Pen* pen, const Rect& rect); Status DrawEllipse(const Pen* pen, INT x, INT y, INT width, INT height) Status DrawEllipse(const Pen* pen, const RectF& rect); Status DrawEllipse(const Pen* pen, REAL x, REAL y, REAL width, REAL height); ``` 這些方法的功能,與 GDI 中的函數: ``` BOOL Ellipse( int x1, int y1, int x2, int y2 ); ``` 圖 14-13 畫弧方法的輸入參數 類似,但是同樣要注意 GDI+的 DrawEllipse 方法與 GDI 的 Ellipse 函數的主要區別(與畫矩 形的方法與函數類似),是上面的以坐標為參數的第 2、4 個 GDI+畫橢圓方法的后兩個輸入 參數,也是矩形的寬高而不再是矩形的右下角坐標了。 (4)畫[橢]圓弧 DrawArc GDI+中也有 4 個重載的繪制橢圓弧的方法,如果輸入參數所確定的外接矩形的寬高相 等,則畫圓弧。也是前兩個為整數版,后兩個為對應的浮點數版。 ![image](https://box.kancloud.cn/2016-04-18_57144a7e4bcac.jpg) ``` Status DrawArc(const Pen* pen, INT x, INT y, INT width, INT height, REAL startAngle, REAL sweepAngle); Status DrawArc(const Pen* pen, const Rect& rect, REAL startAngle, REAL sweepAngle); Status DrawArc(const Pen* pen, REAL x, REAL y, REAL width, REAL height, REAL startAngle, REAL sweepAngle); Status DrawArc(const Pen* pen, const RectF& rect, REAL startAngle, REAL sweepAngle); ``` 注意,角度的單位是度(不是弧度,C++的三角函數 采用的是弧度單位),而且都必須是實數。零度角為 x 軸 方向,順時針方向為正(這與數學上反時針方向為正剛好相反),參見圖 14-13。 (5)畫多邊形 DrawPolygon GDI+中有 2 個重載的繪制多邊形的方法,前一個為整數版,后一個為對應的浮點數版: ``` Status DrawPolygon(const Pen* pen, const Point* points, INT count); Status DrawPolygon(const Pen* pen, const PointF* points, INT count); ``` 其中,各參數的含義同畫折線方法 DrawLines 的,只是 DrawPolygon 方法會將點數組中的起點和終點連接起來,形成一個封閉的多邊形區域。 該方法的功能與 GDI 的 Polygon 函數相同: ``` BOOL Polygon( LPPOINT lpPoints, int nCount ); ``` 注意:GDI+中沒有提供與 GDI 函數 RoundRect(圓角矩形)和 Chord(弓弦)具有類 似功能的繪圖方法,但可以利用矩形+橢圓和弧+直線等方法來自己實現。 ### 1.6.4 畫填充圖的方法 在 GDI 中,任何畫封閉區域的性狀圖繪制函數(如矩形、圓角矩形、[橢]圓、弓弦和多 邊形等),都可以畫填充圖,因為它們總是在用當前筆畫指定邊框的同時,也用當前刷子填 充內部區域。 而 GDI+的畫線方法就沒有這個功能,因為在 GDI+是無狀態的,沒有當前筆和刷的概 念。為了完成與這些 GDI 函數類似的功能,在 GDI+中,你得分兩步來做:先用填充方法填 充區域內部,再用畫線方法繪制邊框。 在 GDI+中畫填充圖,不需像 GDI 那樣得先將刷子選入 DC,而是與 GDI+畫線狀圖的 方法類似,將刷子作為畫填充圖方法的第一個輸入參數。注意,GDI+中的畫填充圖的方法 都以 Fill 開頭。 (1) 畫填充矩形[組]FillRectangle[s] GDI+中有 6 個重載的繪制填充矩形[組]的方法,前 3 個為整數版,后 3 個為對應的浮點 數版: ``` Status FillRectangle(const Brush* brush, const Rect& rect); Status FillRectangle(const Brush* brush, INT x, INT y, INT width, INT height); Status FillRectangles(const Brush* brush, const Rect* rects, INT count); Status FillRectangle(const Brush* brush, const RectF& rect); Status FillRectangle(const Brush* brush, REAL x, REAL y, REAL width, REAL height); Status FillRectangles(const Brush* brush, const RectF* rects, INT count); ``` 用指定刷子 Brush,填充 rect 的內部區域,無邊線,填充區域包括矩形的左邊界和上邊 界,但不包括矩形的右邊界和下邊界。功能與 GDI 的 FillRect 函數類似: ``` void FillRect( LPCRECT lpRect, CBrush* pBrush ); ``` 但是,GDI 中沒有同時填充一個矩形數組的函數。不過 GDI 卻有 GDI+中所沒有的畫填充圓 角矩形的函數 FillSolidRect。 (2) 畫填充橢圓 FillEllipse GDI+中有 4 個重載的繪制填充橢圓的方法,前 2 個為整數版,后 2 個為浮點數版: ``` Status FillEllipse(const Brush* brush, const Rect& rect); Status FillEllipse(const Brush* brush, INT x, INT y, INT width, INT height); Status FillEllipse(const Brush* brush, const RectF& rect); Status FillEllipse(const Brush* brush, REAL x, REAL y, REAL width, REAL height); ``` GDI 中沒有類似函數,但可以用(采用當前刷填充的)Ellipse 函數來代替。 (3) 畫餅圖 DrawPie GDI+中有 4 個重載的繪制餅圖的方法,前 2 個為整數版,后 2 個為浮點數版: ``` Status DrawPie(const Pen* pen, const Rect& rect, REAL startAngle, REAL sweepAngle); Status DrawPie(const Pen* pen, INT x, INT y, INT width, INT height, REAL startAngle, REAL sweepAngle); Status DrawPie(const Pen* pen, const RectF& rect, REAL startAngle, REAL sweepAngle); Status DrawPie(const Pen* pen, REAL x, REAL y, REAL width, REAL height, REAL startAngle, REAL sweepAngle); ``` 與 GDI 的下列函數類似,但是部分輸入參數的含義有所不同: ``` BOOL Pie( int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4 ); BOOL Pie( LPCRECT lpRect, POINT ptStart, POINT ptEnd ); ``` 例如(參見圖 14-14): ![image](https://box.kancloud.cn/2016-04-18_57144a7e5d0ef.jpg) ``` void DrawPies(Graphics &graph, const Color cols[], Point &O, int r, const float data[], int n) { Rect rect(O.X - r, O.Y - r, 2 * r, 2 * r); float startAngle = 0, sweepAngle; for (int i = 0; i &lt; n; i++) { sweepAngle = data[i] * 360.0f; graph.FillPie(&SolidBrush(cols[i]), rect, startAngle, sweepAngle); startAngle += sweepAngle; } } void CGdipDrawView::OnDraw(CDC* pDC) { …… Graphics graph(pDC-&gt;m_hDC); Color cols[] = {Color::Red, Color::Green, Color::Blue, Color::Aqua}; float data[] = {0.2f, 0.4f, 0.1f, 0.3f}; DrawPies(graph, cols, Point(200, 200), 100, data, 4); …… } ``` (4) 畫填充多邊形 FillPolygon GDI+中有 4 個重載的繪制填充多邊形的方法,前 2 個為整數版,后 2 個為浮點數版: ``` Status FillPolygonconst Brush* brush, const Point* points, INT count); Status FillPolygon(const Brush* brush, const Point* points, INT count, FillMode fillMode); Status FillPolygon(const Brush* brush, const PointF* points, INT count); Status FillPolygon(const Brush* brush, const PointF* points, INT count, FillMode fillMode); ``` 其中,填充模式參數 FillMode,可取如下兩個值之一(參見 8.5.3 中的 1.): ``` typedef enum { FillModeAlternate, // 交替模式——按奇偶規則填充(默認模式) FillModeWinding // 環繞模式——按非零環繞規則填充 } FillMode; ``` 對簡單圖形,這兩種模式的效果是一樣的,但對復雜圖形,特別是有穿插的圖,結果可 能是不同的。例如(畫五角星,參見圖 14-15): ``` // 定義五角星頂點數組 const int n = 5; Point p1(100, 0); Point p2(195, 69); Point p3(159, 181); Point p4(41, 181); Point p5(5, 69); Point ps0[n] = {p1, p2, p3, p4, p5}; Point ps[n] = {p1, p3, p5, p2, p4}; // 創建實心刷對象 SolidBrush redBrush(Color(128, 0, 0)); SolidBrush greenBrush(Color(0, 128, 0)); SolidBrush blueBrush(Color(0, 0, 128)); // 畫五角星 Graphics graph(pDC->m_hDC); graph.DrawPolygon(&Pen(Color::Red), ps0, n); graph.DrawPolygon(&Pen(Color::Green), ps, n); // 畫填充五角星 graph.TranslateTransform(200, 0); // 右移 200 像素 graph.FillPolygon(&redBrush, ps0, n); graph.TranslateTransform(200, 0); graph.FillPolygon(&greenBrush, ps, n, FillModeAlternate); graph.TranslateTransform(200, 0); graph.FillPolygon(&blueBrush, ps, n, FillModeWinding); ``` ![image](https://box.kancloud.cn/2016-04-18_57144a7e6df84.jpg) 多邊形 交替/環繞模式 交替模式 環繞模式 圖 14-15 填充多邊形(五角星) GDI 中也沒有與畫填充多邊形類似的專門函數,但可以用(采用當前刷填充的)Polygon 來代替。 ### 1.6.5 畫曲線的方法 前面講的各種畫線狀圖或填充圖的 GDI+方法,雖然在形式上與 GDI 的有所不同(方法 名前加了 Draw 或 Fill、將筆或刷作為第一個輸入參數、部分輸的位置入參數改成了大小參 數、并增加了浮點數版),但是在功能上卻是相同的。 現在要講的曲線繪制,則是 GDI+新增加的內容。曲線在機械設計、工程建筑和圖形動 畫等領域,都有十分廣泛應用。 常用的曲線有 Bezier(貝塞爾)曲線和樣條(spline)曲線。貝塞爾曲線比較簡單,適 合于畫控制點少的曲線。當控制點太多時,要不曲線的次數(比點數少 1)太高,要不拼接 比較困難,而且沒有局部性(即修改一點影響全局),性能不太好。而樣條曲線則可以畫任 意多個控制點的曲線,曲線的次數也可以指定(一般為二次或三次),并且具有局部性。貝 塞爾曲線特別是樣條曲線有很多變種。常見的貝塞爾曲線有普通貝塞爾曲線和有理貝塞爾曲 線。常用的樣條曲線有:B 樣條、β 樣條、Hermite(厄密)樣條、基樣條(cardinal splines)、 Kochanek- Bartels 樣條和 Catmull-Rom 樣條等。 GDI+中所實現的是普通貝塞爾曲線(不過控制點,位于控制多邊形的凸包之內)和基 樣條曲線(過控制點)。有關曲線和曲面構造方法,會在課程《計算機圖形學》中介紹。 (1)基樣條曲線(cardinal spline curve) ``` Status DrawCurve(const Pen* pen, const Point* points, INT count, REAL tension = 0.5f); Status DrawCurve(const Pen* pen, const PointF* points, INT count, REAL tension = 0.5f); Status DrawClosedCurve(const Pen *pen, const Point* points, INT count, REAL tension = 0.5f); Status DrawClosedCurve(const Pen *pen, const PointF* points, INT count, REAL tension = 0.5f); ``` 其中: + 參數 tension(張力)指定曲線的彎曲程度,tension = 0.0(直線)~1.0(最彎曲)。 + DrawClosedCurve 方法(連接首尾點)畫封閉的基樣條曲線。 例如(參見圖 14-16): ``` void DrawPoints(Graphics &graph, const Color &col, int r, const Point* points, INT count) { // 自定義的畫點列函數 SolidBrush brush(col); for (int i = 0; i < count; i++) graph.FillEllipse(&brush, Rect(points[i].X - r, points[i].Y - r, 2 * r, 2 * r)); } Graphics graph(pDC->m_hDC); // 定義 Pen 對象和 Point 對象的數組 Pen greenPen(Color::Green, 3); Point p1(10, 100), p2(100, 50), p3(300, 10), p4(400, 100); Point ps[4] = {p1, p2, p3, p4}; // 繪制不同張力的基樣條曲線 graph.DrawCurve(&Pen(Color::Magenta), ps, 4, 1.0); graph.DrawCurve(&greenPen, ps, 4, 0.5); graph.DrawCurve(&Pen(Color::Blue), ps, 4, 0.0); DrawPoints(graph, Color::Red, 5, ps, 4); // 繪制曲線的控制點 // 繪制默認張力的基樣條、封閉基樣條與貝塞爾曲線 graph.TranslateTransform(450, 0); // 水平右移 450 個像素 graph.DrawCurve(&greenPen, ps, 4); graph.DrawClosedCurve(&Pen(Color::Aqua), ps, 4); graph.DrawBeziers(&Pen(Color::Chocolate), ps, 4); DrawPoints(graph, Color::Red, 5, ps, 4); // 繪制曲線的控制點 ``` ![image](https://box.kancloud.cn/2016-04-18_57144a7e84b80.jpg) 不同張力的基樣條曲線 基樣條、封閉基樣條與貝塞爾曲線 圖 14-16 基樣條曲線與貝塞爾曲線 (2)貝塞爾曲線(Bezier curve) ``` Status DrawBezier(const Pen* pen, INT x1, INT y1, INT x2, INT y2, INT x3, INT y3, INT x4, INT y4); Status DrawBezier(const Pen* pen, const Point& pt1, const Point& pt2, const Point& pt3, const Point& pt4); Status DrawBeziers(const Pen* pen, const Point* points, INT count); ... // 對應的浮點版本 ``` (3)填充封閉基樣條曲線 ``` Status FillClosedCurve(const Brush* brush, const Point* points, INT count); Status FillClosedCurve(const Brush* brush, const Point* points, INT count, FillMode fillMode, REAL tension = 0.5f); ... // 對應的浮點版本 ``` 例如,將前面畫圖 14-15 所對應的填充多邊形例子中的畫填充五角星的三個語句中的 FillPolygon 方法,改為填充封閉基樣條曲線方法 FillClosedCurve,結果如圖 14-17 所示。 ![image](https://box.kancloud.cn/2016-04-18_57144a7e988f8.jpg) 多邊形 交替/環繞模式 交替模式 環繞模式 圖 14-17 填充閉曲線 ### 1.6.6 平滑處理 可以利用 Graphics 類的設置平滑模式方法 ``` Status SetSmoothingMode(SmoothingMode smoothingMode); ``` 來設置繪圖時的平滑化處理。其中的輸入參數為枚舉類型: ``` typedef enum { SmoothingModeInvalid = QualityModeInvalid, //無效(保留) SmoothingModeDefault = QualityModeDefault, // 默認(低質,無平滑處理) SmoothingModeHighSpeed = QualityModeLow, // 高速(低質,無平滑處理) SmoothingModeHighQuality = QualityModeHigh, // 高質(使用 8*4 盒過濾器) SmoothingModeNone, // 無平滑處理 SmoothingModeAntiAlias8x4, // 使用 8*4 盒過濾器(庫中無) SmoothingModeAntiAlias = SmoothingModeAntiAlias8x4, // 使用 8*4 盒過濾器 SmoothingModeAntiAlias8x8 // 使用 8*8 盒過濾器(最高質,庫中也無) } SmoothingMode; ``` ![image](https://box.kancloud.cn/2016-04-18_57144a7eaafb0.jpg) 圖 14-18 平滑處理 例如(參見圖 14-18): ``` Graphics graph(pDC-&gt;m_hDC); Pen pen(Color::Black, 4); Rect rect(10, 10, 200, 200); graph.DrawRectangle(&pen, rect); graph.RotateTransform(1); graph.TranslateTransform(20, 20); //graph.SetSmoothingMode(SmoothingModeNone); graph.DrawRectangle(&pen, rect); graph.TranslateTransform(20, 20); graph.SetSmoothingMode(SmoothingModeAntiAlias); graph.DrawRectangle(&pen, rect); ``` ### 1.6.7 清屏方法 Clear GDI 中沒有用于清屏的專門函數,得自己用背景色畫窗口大小的填充矩形,或者調用窗 口類的 Invalidate 和 UpdateWindow 函數。現在,GDI+有了清屏方法 Clear: ``` Status Clear(const Color &color); ``` 其中的輸入參數 color,為用戶指定的填充背景色。例如: ``` Graphics graph(GetDC()->m_hDC); …… graph.Clear(Color::White); ```
                  <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>

                              哎呀哎呀视频在线观看