代码实现的优点粗燥,思路是这么个思路。
方法1. 在timer里面每次重画窗口
LRESULT Demo::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_PAINT:
{
PAINTSTRUCT ps;
RECT r;
HDC hdc = BeginPaint(hWnd, &ps);
HFONT hFont, hOldFont;
GetClientRect(hWnd, &r);
// 如果窗口颜色不是我们想要的,就填充一下以修改客户区的颜色
HBRUSH hbr = (HBRUSH)CreateSolidBrush(RGB(255, 0, 0));
FillRect(hdc, &r, hbr);
HDC hdcImage = ::CreateCompatibleDC(hdc);
HBITMAP hBitmap = ::CreateCompatibleBitmap(hdc, r.right - r.left, r.bottom - r.top);//hdcImage
HBITMAP hOldBitmap = (HBITMAP)::SelectObject(hdcImage, hBitmap);
LOGFONT logfont;
ZeroMemory(&logfont, sizeof(LOGFONT));
logfont.lfCharSet = DEFAULT_CHARSET;
logfont.lfHeight = -36;
lstrcpy(logfont.lfFaceName, L"Arial");
hFont = CreateFontIndirect(&logfont);
if (hOldFont = (HFONT)SelectObject(hdcImage, hFont))
{
SetBkMode(hdcImage, TRANSPARENT);
COLORREF color = RGB(255, 255, 255);
::SetTextColor(hdcImage, color);
size_t WLength = MultiByteToWideChar(CP_UTF8, 0, msg.C_str(), -1, NULL, NULL);
LPWSTR pszW = (LPWSTR)_alloca((WLength + 1) * sizeof(WCHAR)); //do not need free
MultiByteToWideChar(CP_UTF8, 0, msg.C_str(), -1, pszW, WLength);
pszW[WLength] = 0;
SIZE msgSize;
::GetTextExtentPointW(hdcImage, pszW, WLength, &msgSize);
HWND mainWnd = (HWND)*g_MainWnd;
RECT rect;
::GetClientRect(mainWnd, &r);
rect.left = r.right - _msgStartPos;
rect.top = (r.bottom - r.top - msgSize.cy) / 2;
rect.right = rect.left + msgSize.cx;
rect.bottom = rect.top + msgSize.cy;
//_msgStartPos 是这个类的全局变量,初始值是0.
::TextOutW(hdcImage, r.right - _msgStartPos, (r.bottom - r.top - _msgSize.cy) / 2, pszW, WLength - 1);
_msgStartPos += 20;
if (_msgStartPos > r.right + _msgSize.cx)
{
::KillTimer(hWnd, 1);
::ShowWindow(hWnd, SW_HIDE);
}
SelectObject(hdcImage, hOldFont);
}
BitBlt(hdc, 0, 0, r.right - r.left, r.bottom - r.top, hdcImage, 0, 0, SRCPAINT);
::SelectObject(hdcImage, hOldBitmap);
DeleteObject(hBitmap);
DeleteDC(hdcImage);
DeleteObject(hFont);
EndPaint(hWnd, &ps);
return 1;
}
case WM_TIMER:
{
RedrawWindow(hWnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW);
}
break;
default:
break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
方法2. 给窗口贴一个static,每次移动static的位置
LRESULT Demo::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_NCCREATE:
{
CREATESTRUCT* cs = (CREATESTRUCT*)lParam;
LPVOID pWnd = cs->lpCreateParams;
SetWindowLongPtr(hWnd, GWL_USERDATA, (LONG)pWnd);
::PostMessageW(hWnd, WM_ERASEBKGND, 1, 0);
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_CREATE:
{
HFONT hFont;
LOGFONT logfont;
ZeroMemory(&logfont, sizeof(LOGFONT));
logfont.lfCharSet = DEFAULT_CHARSET;
logfont.lfHeight = -36;
lstrcpy(logfont.lfFaceName, L"Arial");
hFont = CreateFontIndirect(&logfont);
_msgStatic = CreateWindow(L"STATIC", L"", WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
0, 0, 1280, 56, hWnd, (HMENU)IDS_OVERLAY_MSG, NULL, NULL);
_bkStatic = CreateWindow(L"STATIC", L"", WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
0, 0, 1280, 56, hWnd, (HMENU)IDS_OVERLAY_MSG, NULL, NULL);
::PostMessageW(_msgStatic, WM_ERASEBKGND, 1, 0);
::PostMessageW(_bkStatic, WM_ERASEBKGND, 1, 0);
::PostMessageW(_msgStatic, WM_SETFONT, (WPARAM)hFont, 1);
}
break;
case WM_CTLCOLORSTATIC:
{
SetTextColor((HDC)wParam, RGB(255, 255, 255));//set text color
SetBkMode((HDC)wParam, TRANSPARENT);
HBRUSH brush = (HBRUSH)CreateSolidBrush(RGB(255, 0, 0));
return (LONG)brush;
}
break;
case WM_TIMER:
{
RECT wndRect;
::GetClientRect(hWnd, &wndRect);
// 要显示的内容在这个函数外面已经set到了static上,具体方法参考方法1中的实现
//_msgSize是在外面算好的,需要显示的字符所占的size
SetWindowPos(_msgStatic, NULL, wndRect.right - _msgStartPos, (wndRect.bottom - wndRect.top - _msgSize.cy) / 2, _msgSize.cx, _msgSize.cy, SWP_NOZORDER);
_msgStartPos += 20;
if (_msgStartPos > wndRect.right + _msgSize.cx)
{
_msgStartPos = 0;
::KillTimer(hWnd, 1);
::ShowWindow(hWnd, SW_HIDE);
}
}
break;
default:
break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}