首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

GDI+ 繪製圓角矩形:GraphicsPath 構建路徑支援紋理與透明填充

     編輯:關於VC++

GDI+ 提供豐富的繪圖原語 (線、橢圓、矩形、路徑),但缺乏直接繪製圓角矩形的函數。若呼叫 GDI RoundRect 則失去 GDI+ 紋理筆刷、漸層、透明度等進階特性。解決方案:使用 GraphicsPath 組合四條弧線與四條直線構建圓角矩形路徑,再以任意 Brush 填充或 Pen 描邊。

MakeRoundRect 函數實作


GraphicsPath* MakeRoundRect(Point topLeft, Point bottomRight, INT percentageRounded)
{
    // 參數驗證
    ASSERT(percentageRounded >= 1 && percentageRounded <= 100);
    
    // 正規化座標
    INT left   = min(topLeft.X, bottomRight.X);
    INT right  = max(topLeft.X, bottomRight.X);
    INT top    = min(topLeft.Y, bottomRight.Y);
    INT bottom = max(topLeft.Y, bottomRight.Y);
    
    // 圓角半徑 = 短邊長度 * percentage / 100
    INT offsetX = (right - left) * percentageRounded / 100;
    INT offsetY = (bottom - top)  * percentageRounded / 100;
    
    // 構建路徑:順時針四個 90° 圓弧 + 閉合
    GraphicsPath tempPath;
    GraphicsPath* path = tempPath.Clone(); // GDI+ 禁止 new GraphicsPath,需用 Clone
    
    // 右上角 (270°→360°)
    path->AddArc(right - offsetX, top, offsetX, offsetY, 270, 90);
    // 右下角 (0°→90°)
    path->AddArc(right - offsetX, bottom - offsetY, offsetX, offsetY, 0, 90);
    // 左下角 (90°→180°)
    path->AddArc(left, bottom - offsetY, offsetX, offsetY, 90, 90);
    // 左上角 (180°→270°)
    path->AddArc(left, top, offsetX, offsetY, 180, 90);
    // 閉合頂邊直線
    path->AddLine(left + offsetX, top, right - offsetX/2, top);
    
    return path; // 呼叫端負責 delete
}

關鍵技術細節

為何用 Clone() 而非 new?

GDI+ 類別 (GraphicsPath, Bitmap, Font 等) 內部使用參考計數/共享控制代碼機制,直接 new GraphicsPath 會導致執行階段錯誤。正確模式:建立區域暫存物件 → Clone() 取得堆疊配置的獨立實例 → 回傳指標。此設計為配合 .NET 語言 (無指標) 的統一物件模型。

percentageRounded 參數化圓角程度

  • 1 → 極微圓角 (近似銳角)
  • 50 → 圓角半徑 = 短邊一半 (長方形變膠囊形)
  • 100 → 圓角半徑 = 短邊 (正方形變圓形)

搭配滑桿控制項即時調整,極適合 UI 原型設計。

使用範例


void CMyView::OnDraw(CDC* pDC)
{
    Graphics g(pDC->GetSafeHdc());
    
    // 1. 建立圓角矩形路徑
    GraphicsPath* path = MakeRoundRect(Point(50,50), Point(300,200), 30);
    
    // 2. 紋理筆刷填充
    TextureBrush brush(L"texture.jpg", WrapModeTile);
    g.FillPath(&brush, path);
    
    // 3. 半透明紅色描邊
    Pen pen(Color(180, 255, 0, 0), 3.0f);
    g.DrawPath(&pen, path);
    
    delete path; // 釋放
}

擴充應用:對話框氣泡、按鈕、標籤頁

同樣路徑可用於:

  • 聊天氣泡:三角形尖端 + 圓角矩形主體 → AddPolygon + AddArc 組合
  • 圓角按鈕:滑鼠進入/按下切換筆刷顏色,GraphicsPath 做 IsVisible 點擊測試
  • 標籤頁:僅頂部兩角圓角 → percentageRounded 僅套用上偏移

設計缺限與改進

  • ⚠️ 函數回傳 GraphicsPath* 需呼叫端 delete,易忘記洩漏。建議改回傳 std::unique_ptr (C++11) 或封裝為 RAII 類別。
  • ⚠️ AddLine(left + offsetX, top, right - offsetX/2, top) 結尾座標應為 right - offsetX,原碼 /2 疑為筆誤。
  • ✅ 可進一步加入 AddRectangle、AddEllipse 等輔助函數構建幾何圖形庫。

總結

GraphicsPath 是 GDI+ 矢量繪圖核心,掌握路徑構建即可繪製任意複雜形狀並享受完整筆刷/筆畫功能。MakeRoundRect 以參數化圓角程度展示路徑組合技巧,可直接整合至專案作為 UI 繪圖基元。完整原始碼含滑桿即時調整圓角示範專案,請下載附件。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved