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;
}
4

2 に答える 2

2

InvalidateRect()またはUpdateWindow()から呼び出さないでくださいWM_PAINT。再描画の無限ループが作成されます。

からペイントしないでくださいWM_TIMER。それはできます(GetWindowDC()代わりにのを使用しますBeginPaint()が、あまり良い考えではありません.

代わりに を に入れ、描画コードは のままにしておきInvalidateRect()ます。@typ1232 がコメントで述べたように、フォントを 1 回だけ作成することで最適化できますが、厳密には必要ありません。WM_TIMERWM_PAINT

UpdateWindow()タイトな CPU ループにあり、今ウィンドウを表示する必要がない限り、呼び出しは通常必要ありません: 無効化がタイマーで行われ、タイムアウトが短すぎない場合は、必要ありません。ただし、タイムアウトが非常に短い場合は、 のUpdateWindow()直後に再描画呼び出しを強制できますInvalidateRect()

于 2013-07-16T13:39:28.843 に答える
2

WM_TIMER コードは、描画する文字列を準備して保存し、InvalidateRect を呼び出す必要があります。WM_TIMER コードは直接描画できません。その理由の 1 つは、WM_TIMER メッセージ中に BeginPaint が正しく動作しないことです。BeginPaint は、WM_PAINT メッセージ中にのみ定義されます。したがって、WM_TIMER は描画するデータを準備できますが、InvalidateRect を使用して WM_PAINT の生成を要求します。

また、WM_PAINT コードから InvalidateRect および UpdateWindow 呼び出しを削除する必要があります。それらはペイントの無限ループを引き起こします。

于 2013-07-16T13:40:15.237 に答える