[ATL/WTL]_[Gdiplus]_[關於使用Gdiplus來繪製反鋸齒的圓角矩形]
阿新 • • 發佈:2018-12-01
場景
-
在使用WTL或MFC開發自定義按鈕時, 往往美工設計的按鈕都時圓角矩形的. 用
GDI
的函式RoundRect
函式可以簡便的繪製圓角矩形, 但是如果橢圓(ellipse)的寬高比較大的時候, 按鈕比較大. 這時候按鈕的圓角矩形看起來就是有鋸齒的(aliasing). -
在
GDI
的函式裡, 沒有比較好的函式來實現抗鋸齒(antialias), 如果不想自己去解決鋸齒效果, 只能使用Gdiplus來解決.
說明
-
Gdiplus沒有自己的
RoundRect
函式, 所以需要自己實現一個. 其實圓角就是直角座標系以橢圓形的圓心為原點分割4部分, 在4個角分別繪製橢圓的4個部分, 之後再由上下左右4條直線組成. -
關鍵的函式還是
graphics.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
, 沒有這個, 繪製出來的圓角矩形和RoundRect
是一樣的, 有鋸齒.
例子
圖示
// Create round rect path. void CreateRoundRect(Gdiplus::GraphicsPath& m_pPath, Gdiplus::Rect rect, int cornerRadius) { // https://docs.microsoft.com/en-us/windows/desktop/api/gdipluspath/nf-gdipluspath-graphicspath-addarc%28inreal_inreal_inreal_inreal_inreal_inreal%29 m_pPath.AddArc(rect.X, rect.Y, cornerRadius * 2, cornerRadius * 2, 180, 90); m_pPath.AddLine(rect.X + cornerRadius, rect.Y, rect.GetRight() - cornerRadius * 2, rect.Y); m_pPath.AddArc(rect.X + rect.Width - cornerRadius * 2, rect.Y, cornerRadius * 2, cornerRadius * 2, 270, 90); m_pPath.AddLine(rect.GetRight(), rect.Y + cornerRadius * 2, rect.GetRight(), rect.Y + rect.Height - cornerRadius * 2); m_pPath.AddArc(rect.X + rect.Width - cornerRadius * 2, rect.Y + rect.Height - cornerRadius * 2, cornerRadius * 2, cornerRadius * 2, 0, 90); m_pPath.AddLine(rect.GetRight() - cornerRadius * 2, rect.GetBottom(), rect.X + cornerRadius * 2, rect.GetBottom()); m_pPath.AddArc(rect.X, rect.GetBottom() - cornerRadius * 2, cornerRadius * 2, cornerRadius * 2, 90, 90); m_pPath.AddLine(rect.X, rect.GetBottom() - cornerRadius * 2, rect.X, rect.Y + cornerRadius * 2); m_pPath.CloseFigure(); } void DrawRectangle(CDC& dc,Gdiplus::Graphics& graphics) { // Gdi // https://docs.microsoft.com/en-us/windows/desktop/api/wingdi/nf-wingdi-roundrect CRect rect(300,500,300+128,500+50); CPen pen_gdi; pen_gdi.CreatePen(PS_SOLID,2,RGB(255,0,0)); dc.SelectPen(pen_gdi); CBrush brush_gdi; brush_gdi.CreateSolidBrush(RGB(0,0,0)); dc.SelectBrush(brush_gdi); dc.RoundRect(rect,CPoint(8*2,8*2)); // Gdiplus // https://docs.microsoft.com/en-us/windows/desktop/api/gdipluspath/nf-gdipluspath-graphicspath-addarc%28inreal_inreal_inreal_inreal_inreal_inreal%29 Gdiplus::Rect rcShadow(300,400,128, 50); Gdiplus::GraphicsPath m_pPath; Gdiplus::Pen pen(Gdiplus::Color(255,0,0),2); CreateRoundRect(m_pPath,rcShadow, 8); Gdiplus::SolidBrush brShadow(Gdiplus::Color(0,0,0)); graphics.FillPath(&brShadow,&m_pPath); auto status = graphics.DrawPath(&pen,&m_pPath); } LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) { CPaintDC dc(m_hWnd); Gdiplus::Graphics graphics(dc); // 注意, 得新增這句實現繪製圖形時有反鋸齒效果. 不然用Gdiplus和Gdi都有鋸齒. graphics.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); DrawRectangle(dc,graphics); return 0; }