[ATL/WTL]_[Gdiplus]_[實現按鈕的陰影效果]
阿新 • • 發佈:2018-12-01
場景
-
在
WTL
開發時, 由於介面需要, 很多按鈕都是奇形怪狀的. 比如卡片形狀, 圓角矩形等等. 只要是點選能響應一個事件的, 我們都可以看做是一個異形按鈕. 其中讓按鈕呈現立體效果, 動畫效果等一直是實現自定義按鈕的難點. -
系統按鈕一般是帶3D效果的按鈕. 我們這裡實現自帶陰影效果的按鈕一樣具備很好的特效, 陰影按鈕特別適合在面積比較大的卡片按鈕上.
說明
-
Gdiplus視窗實現陰影效果可以參考 VC++介面程式設計之–陰影視窗的實現詳解. 這個效果不合適自定義的按鈕,因為按鈕並不是頂層視窗. 實際上可以參考繪製陰影的部分在按鈕的部分割槽域繪製陰影效果,這樣也是可以的, 這樣也省了建立額外視窗的開銷.
-
Gdiplus實現陰影的其中一種方式是使用
PathGradientBrush
, 也就是漸變的畫刷來繪製陰影部分. 其實也很好理解, 因為陰影部分其實也是模糊的黑色效果. 在藉助graphics.ExcludeClip
來排除正常的按鈕部分, 只繪製陰影區域, 能很好的不影響正常的區域.
例子
圖示
系統按鈕
陰影按鈕
// 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 DrawShadow(CDC& dc,Gdiplus::Graphics& graphics) { Gdiplus::Rect rect_button(600,400,128, 50); Gdiplus::GraphicsPath m_pPath; Gdiplus::Pen pen(Gdiplus::Color(255,0,0),2); CreateRoundRect(m_pPath,rect_button, 8); Gdiplus::Rect rcShadow = rect_button; rcShadow.Width+=6; rcShadow.Height+=6; Gdiplus::GraphicsPath shadow_path; CreateRoundRect(shadow_path,rcShadow,8); Gdiplus::PathGradientBrush brShadow(&shadow_path); Gdiplus::Color clrShadow[3] = {Gdiplus::Color::Transparent,Gdiplus::Color(255, 0, 0, 0), Gdiplus::Color(255, 0, 0, 0)}; int nCount = 3; Gdiplus::REAL szPos[3] = {0.0F, 0.1F,1.0F}; brShadow.SetInterpolationColors(clrShadow, szPos, nCount); Gdiplus::Region region(&m_pPath); graphics.ExcludeClip(®ion); graphics.FillPath(&brShadow,&shadow_path); graphics.ResetClip(); 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); //DrawText(dc,graphics); //DrawRectangle(dc,graphics); DrawShadow(dc,graphics); return 0; }
參考
VC++介面程式設計之–陰影視窗的實現詳解
PathGradientBrush::SetInterpolationColors method