2013-07-16 53 views
0

我用內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

創建字體非常CPU密集型工作。嘗試只做一次,而不是每個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()調用通常不應該是必要的,除非你是在一個緊密的CPU循環,並需要顯示窗口剛纔:如果失效是在一個計時器中完成,超時時間不會太短,但如果超時時間很短,可以強制重新調用UpdateWindow()就在InvalidateRect()之後。

2

你WM_TIMER代碼應該準備要繪製的字符串,將其保存,然後調用InvalidateRect。 WM_TIMER代碼無法直接繪製,原因之一是BeginPaint在WM_TIMER消息期間無法正常工作。 BeginPaint僅在WM_PAINT消息期間定義。因此WM_TIMER可以準備要繪製的數據,但是然後使用InvalidateRect來請求生成WM_PAINT。

您還必須刪除InvalidateRect並UpdateWindow從WM_PAINT代碼調用。他們會導致無限的繪畫循環。