為避免引入外部 OCX 控制項增加部署複雜度,且解決原控制項長文字重繪異常問題,本文實作一個繼承自 CStatic 的純 MFC 跑馬燈控制項 CScrollCtrl。採用雙緩衝繪圖,配合定時器動態調整文字輸出矩形左邊界,實現文字從右向左平滑捲動。
DrawCtrlBackgroundm_clBkColor。m_nTextWidth,初始化文字起始 X 座標 m_nXPos 為控制項右邊界(文字寬度)。DrawCtrlTextTRANSPARENT、文字顏色 m_clTextColor、選入字型 m_pFnt。left = m_nXPos、right = 控制項右邊界、垂直置中。DrawText 搭配 DT_LEFT | DT_VCENTER | DT_SINGLELINE 繪製。OnTimer 中遞減 m_nXPos。m_nXPos < -m_nTextWidth 時重置為控制項寬度,形成循環捲動。Invalidate() 觸發重繪。OnPaint → 建立記憶體 DC → 雙緩衝繪圖 → BitBlt 至螢幕 DC,消除閃爍。void CScrollCtrl::DrawCtrlBackground(CDC *pDC, CRect &rect)
{
CBrush newBrush, *pOldBrush;
newBrush.CreateSolidBrush(m_clBkColor);
pOldBrush = (CBrush*)pDC->SelectObject(&newBrush);
pDC->FillRect(&rect, &newBrush);
pDC->SelectObject(pOldBrush);
newBrush.DeleteObject();
CSize sSize = pDC->GetTextExtent(m_strText);
m_nXPos = sSize.cx; // 重置至右邊界
}
void CScrollCtrl::DrawCtrlText(CDC *pDC, CRect rect)
{
CRect rectText;
CFont *pOldFont;
pDC->SetBkMode(TRANSPARENT);
pDC->SetTextColor(m_clTextColor);
pOldFont = (CFont*)pDC->SelectObject(m_pFnt);
CSize sSize = pDC->GetTextExtent(m_strText);
m_nTextWidth = sSize.cx;
rectText.left = m_nXPos;
rectText.top = rect.top;
rectText.bottom = rect.bottom;
rectText.right = rect.right;
pDC->DrawText(m_strText, rectText, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
pDC->SelectObject(pOldFont);
}
ScrollCtrl.h、ScrollCtrl.cpp 加入專案。IDC_SCROLL_CTRL,類型選 Frame。m_ScrollCtrl,類型指定 CScrollCtrl。OnInitDialog 設定屬性:SetBkColor、SetTextColor、SetFont、SetWindowText、啟動定時器。GradientFill)。演示效果圖:

完整原始碼可下載,歡迎回饋改進建議至 successq_g@163.com。