傳統文字陰影只是偏移繪製不同顏色文字,效果生硬。本文利用 GDI+ 的 反走樣 與 高質量雙三次插值 實現真實的軟陰影/半陰影效果:
InterpolationModeHighQualityBicubicvoid CDropShadowEffectTextView::OnDraw(CDC* pDC) {
using namespace Gdiplus;
CDropShadowEffectTextDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc) return;
CRect ClientRect;
GetClientRect(&ClientRect);
CSize ClientSize(ClientRect.Width(), ClientRect.Height());
RectF theRect(ClientRect.left, ClientRect.top, ClientRect.Width(), ClientRect.Height());
PointF textPos(10, ClientSize.cy / 3);
CStringW text(L"文字陰影特效");
FontFamily fontFamily(L"Times New Roman");
Font font(&fontFamily, 100, FontStyleBold, UnitPixel);
Graphics g(pDC->m_hDC);
// 背景漸變
LinearGradientBrush b(theRect, Color::Blue, Color::AliceBlue, 90.0f);
g.FillRectangle(&b, theRect);
// 1. 創建 1/4 大小的內存位圖
Bitmap bm(ClientSize.cx / 4, ClientSize.cy / 4, &g);
Graphics* bmpg = Graphics::FromImage(&bm);
// 2. 設置反走樣渲染
bmpg->SetTextRenderingHint(TextRenderingHintAntiAlias);
// 3. 縮放矩陣:縮小 4 倍 + 偏移 (3,3) 模擬陰影位移
Matrix mx(0.25f, 0, 0, 0.25f, 3, 3);
bmpg->SetTransform(&mx);
// 4. 繪製陰影文字(50% 透明黑)
bmpg->DrawString(text, -1, &font, textPos, NULL, &SolidBrush(Color(128, 0, 0, 0)));
// 5. 目標 DC 設置高質量雙三次插值
g.SetInterpolationMode(InterpolationModeHighQualityBicubic);
g.SetTextRenderingHint(TextRenderingHintAntiAlias);
// 6. 放大繪製小位圖 → 產生模糊邊緣的軟陰影
g.DrawImage(&bm, theRect, 0, 0, bm.GetWidth(), bm.GetHeight(), UnitPixel);
// 7. 最後繪製正常文字
g.DrawString(text, -1, &font, textPos, NULL, &SolidBrush(Color::White));
}
| 技術點 | 作用 | 參數說明 |
|---|---|---|
| 縮小繪製 | 將文字光柵化為低分辨率 | Matrix(0.25, 0, 0, 0.25, 3, 3) 縮放 0.25x + 位移 3px |
| 反走樣 | 生成帶 alpha 通道的平滑邊緣 | TextRenderingHintAntiAlias |
| 半透明畫刷 | 模擬陰影透明度 | Color(128, 0, 0, 0) = 50% alpha 黑色 |
| 雙三次插值放大 | 將鋸齒邊緣平滑為漸變陰影 | InterpolationModeHighQualityBicubic |
| 疊加繪製 | 陰影在下、文字在上 | 先 DrawImage 再 DrawString |

左側為普通文字,右側為帶軟陰影效果。JPEG 壓縮導致效果輕微損失,實際運行效果更佳。
此技巧巧妙利用了 GDI+ 的矩陣變換、反走樣光柵化、高質量插值三大特性,以極少代碼實現了媲美專業圖形軟件的文字軟陰影效果。適用於 VC6+GDI+ 到現代 MSVC 所有版本,是 GDI+ 程式設計的經典範例。