如何使用Timer绘制文本?

时间:2013-07-16 13:24:36

标签: c++ windows timer drawtext

我在WM_TIMER中使用了DrawText函数,但它不起作用。如何解决这个问题?谢谢!

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
{
    PAINTSTRUCT ps;
    HDC hdc;
    switch (message)
    {
    case WM_CREATE:
        SetTimer(hwnd,23, 1000,NULL);
        break;

    //case WM_TIMER: ***** dont work *****
    case WM_PAINT: // ***** work, but used 25% CPU *****
        {
        RECT rect;
        HFONT hFont;
        hdc = BeginPaint(hwnd, &ps);
        hFont = CreateFontA(16,0,0,0,FW_NORMAL,FALSE,FALSE,FALSE,DEFAULT_CHARSET,OUT_OUTLINE_PRECIS, CLIP_DEFAULT_PRECIS,ANTIALIASED_QUALITY, VARIABLE_PITCH,TEXT("Arial"));
        SelectObject(hdc,hFont);
        SetRect(&rect, 3, 3, 90, 50);
        SetTextColor(hdc, RGB(0,0,255));

        time_t rawtime;
        struct tm * timeinfo;
        char buffer [80];

        time ( &rawtime );
        timeinfo = localtime ( &rawtime );
        strftime (buffer,80,"%I:%M:%S %p\n%m/%d/%Y",timeinfo);

        wchar_t wtext[30];
        mbstowcs(wtext, buffer, strlen(buffer)+1);//Plus null
        LPWSTR ptr = wtext;



        DrawTextW(hdc, ptr, -1,&rect, DT_NOCLIP | DT_CENTER);

        DeleteObject(hFont);

        InvalidateRect(hwnd, &rect, TRUE);
        UpdateWindow(hwnd);

        EndPaint(hwnd, &ps);
        break;
        }
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hwnd, message, wparam, lparam);
    }
    return 0;
}

2 个答案:

答案 0 :(得分:2)

请勿从InvalidateRect()致电UpdateWindow()WM_PAINT,否则您将创建一个无限循环重绘。

不要从WM_TIMER画画。 可以完成(使用GetWindowDC()代替BeginPaint(),但这不是一个好主意。

而是将InvalidateRect()放在WM_TIMER中,并将绘图代码保留在WM_PAINT中。正如@ typ1232在评论中所说,你可以通过仅创建一次字体进行优化,但这并不是绝对必要的。

通常不需要UpdateWindow()调用,除非您处于紧凑的CPU循环中并且需要立即显示窗口:如果在计时器中完成失效并且超时不会太短则您赢了不需要它。但如果您的超时时间非常短,则可以在UpdateWindow()之后强制重新调用InvalidateRect()

答案 1 :(得分:2)

您的WM_TIMER代码应准备要绘制的字符串,保存它然后调用InvalidateRect。 WM_TIMER代码无法直接绘制,原因之一是BeginPaint在WM_TIMER消息期间无法正常工作。 BeginPaint仅在WM_PAINT消息期间定义。所以WM_TIMER可以准备要绘制的数据,但是然后使用InvalidateRect来请求生成WM_PAINT。

您还必须从WM_PAINT代码中删除InvalidateRect和UpdateWindow调用。它们将导致无限的绘画循环。