2013-07-16 2 views
0

Я использовал функцию DrawText в WM_TIMER, но она не работает. Как это исправить? Спасибо!Как нарисовать текст с таймером?

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

Создание шрифта - это очень интенсивная работа с процессором. Попробуйте сделать это один раз, а не на каждом событии WM_PAINT. – typ1232

+1

Имейте вызов 'WM_TIMER' [' InvalidateRect'] (http://msdn.microsoft.com/en-us/library/windows/desktop/dd145002 (v = vs.85) .aspx). Также, что сказал @ typ1232. –

ответ

2

Не называйте InvalidateRect()UpdateWindow() или из WM_PAINT, или вы будете создавать бесконечный цикл перерисовки.

Не окрашивать из WM_TIMER. Это может быть сделано (с GetWindowDC() вместо BeginPaint() но это не такая хорошая идея.

Вместо поставить InvalidateRect() в WM_TIMER и оставить код рисования в WM_PAINT. Вы можете оптимизировать как @ typ1232 сказал комментарии, создавая шрифт только один раз, но это не обязательно.

Звонок UpdateWindow() обычно не нужен, если только вы не находитесь в жестком цикле процессора и должны показывать окно только сейчас: если недействительность сделанный таймером, и тайм-аут не слишком короткий, вам это не понадобится. Но если ваш тайм-аут очень короткий, вы можете принудительно вызвать вызов redraw UpdateWindow() сразу после InvalidateRect().

2

Ваш код WM_TIMER должен подготовить строку для рисования, сохранить ее и затем вызвать InvalidateRect. Код WM_TIMER не может рисовать напрямую, и одна из причин заключается в том, что BeginPaint не будет работать должным образом во время сообщения WM_TIMER. BeginPaint определяется только во время сообщения WM_PAINT. Таким образом, WM_TIMER может подготовить данные для рисования, но затем использовать InvalidateRect для запроса создания WM_PAINT.

Вы также должны удалить вызовы InvalidateRect и UpdateWindow из кода WM_PAINT. Они вызовут бесконечный цикл живописи.

Смежные вопросы