1. 跑马灯
银行、商店的一些广告牌采用的跑马灯式的滚动字幕,如下图:
2. GDI+实现
使用GDI+双缓冲实现跑马灯效果。
初始化计时器:
int g_nCount; // 控制第一个字符串的前进
int g_nCount2; // 控制第二个字符串的前进
BOOL g_bRestart; // 切换字符串
int g_nControlWidth; // 显示宽度
void CALLBACK MyTimerProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime )
{
switch(idEvent)
{
case 1:
DrawMarquee(hwnd);
break;
default:
break;
}
}
void InitTimer(HWND hwnd)
{
RECT rc;
GetClientRect(hwnd, &rc);
rc.left += 25;
rc.right -= 25;
rc.top += 25;
rc.bottom -= 25;
g_nControlWidth = rc.right - rc.left;
g_nCount = g_nControlWidth;
g_nCount2 = g_nControlWidth;
g_bRestart = TRUE;
SetTimer(hwnd, 1, 200, MyTimerProc);
}
绘制:
void DrawMarquee(HWND hwnd)
{
RECT rc;
GetClientRect(hwnd, &rc);
rc.left += 25;
rc.right -= 25;
rc.top += 25;
rc.bottom -= 25;
int nWidth = rc.right - rc.left;
int nHeight = rc.bottom - rc.top;
Gdiplus::RectF gdiRc(rc.left, rc.top, nWidth, nHeight);
HDC hdc = GetDC(hwnd);
wchar_t strText[] = TEXT("这是一串GdiPlus要显示的字符,正在以走马灯的形式显示...");
Gdiplus::Graphics baseGraph(hdc);
Gdiplus::Bitmap bmp(nWidth, nHeight);
Gdiplus::Color white(0xFF, 0xFF, 0xFF);
for (int x = 0; x < nWidth; x++)
{
for (int y = 0; y < nHeight; y++)
{
bmp.SetPixel(x, y, white);
}
}
Gdiplus::Graphics *pGraphics = Graphics::FromImage(&bmp);
Gdiplus::SolidBrush solidbrush(Color(0xFF, 0x00, 0x00, 0xFF)); // 蓝色画刷
Gdiplus::FontFamily fontFamily(L"微软雅黑");
Gdiplus::Font gdifont(&fontFamily, 16, FontStyleRegular, UnitPixel); // 字体
Gdiplus::StringFormat sf;
sf.SetAlignment(StringAlignmentNear); // 单行靠左
sf.SetLineAlignment(StringAlignmentCenter); // 文本垂直居中显示
pGraphics->SetTextRenderingHint(TextRenderingHintClearTypeGridFit);
pGraphics->SetTextRenderingHint(TextRenderingHintAntiAlias);
Gdiplus::RectF fstRc;
fstRc.X = g_nCount;
fstRc.Y = 0;
fstRc.Width = nWidth;
fstRc.Height = nHeight;
Gdiplus::PointF gdiPt(rc.left + g_nCount, rc.top);
Gdiplus::RectF clipRc;
clipRc.X = 0;
clipRc.Y = 0;
clipRc.Width = nWidth;
clipRc.Height = nHeight;
pGraphics->SetClip(clipRc);
//pGraphics->DrawString(strText, wcslen(strText), &gdifont, gdiPt, &solidbrush);
pGraphics->DrawString(strText, wcslen(strText), &gdifont, fstRc, &sf, &solidbrush);
g_nCount -= 10; // 从右到左递进
if (!g_bRestart)
{
Gdiplus::RectF secRc;
secRc.X = g_nCount2 + 20;
secRc.Y = 0;
secRc.Width = nWidth;
secRc.Height = nHeight;
//Gdiplus::PointF secPt(g_nCount2+20, rc.top);
//pGraphics->DrawString(strText, wcslen(strText), &gdifont, secPt, &solidbrush);
pGraphics->DrawString(strText, wcslen(strText), &gdifont, secRc, &sf, &solidbrush);
g_nCount2 -= 10; // 从右到左递进
if (secRc.X <= -100 && (g_nCount < 0)) // 准备显示第一个字符串
{
g_nCount = g_nControlWidth;
}
if (secRc.X <= (-g_nControlWidth)) // 第二个字符串已经滚动完毕
{
g_bRestart = TRUE;
}
}
baseGraph.DrawImage(&bmp, gdiRc, 0, 0, nWidth, nHeight, UnitPixel);
DeleteDC(hdc);
if (g_nCount <= (-100)) // 第一个字符串已经前进一部分,准备显示第二个字符串
{
if (g_bRestart)
{
g_bRestart = FALSE;
g_nCount2 = g_nControlWidth;
}
}
}
效果图: