Timer



  • Oder Windows-Timer mithilfe von SetTimer nutzen. Dürfte in dem Fall ausreichend sein, wenn du die zeitliche Differenzen zwischen zwei WM_TIMER-Nachrichten selber mit GetTickCount ermittelst (und dann natürlich die Zeit, die vergehen soll, in ms speicherst).



  • Danke für die Tipps!

    Bei der PostMessage-Lösung:
    Muss ich da den neuen Text einfach an die Edit-Control schicken?



  • Ich würde mir es dennoch überlegen, für deine Anwendung reicht ein Thread aus.

    LRESULT WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
    	static DWORD lastTick;
    	static DWORD timeInMs;
    	switch (msg)
    	{
    		case WM_COMMAND:
    			switch(LOWORD(wParam))
    			{
    				case ID_START: // könnte ein Button mit der ID sein, hier soll der Countdown begonnen werden
    					timeInMs=/*initialisieren*/;
                        lastTick = GetTickCount(); // momentanen Wert speichern
    					SetTimer(hwnd,1,1000,NULL); // Windows-Timer anfordern
    					break;
    			}
    			break;
    		case WM_TIMER:
    		{
    			DWORD curTick = GetTickCount(); // momentaner Tick
    			DWORD diff = curTick-lastTick; // Differenz seit letzter Nachricht
    			lastTick = curTick; // wichtig: alten Wert speichern
    			timeInMs-=diff; // Differenz abziehen
    			DWORD time = timeInMs; // Kopie
    			time/=1000; // ms kürzen
    			int second=time%60;
    			time/=60;
    			int minute=time%60;
    			int hour=time/60;
    	        // Editfelder mit SetWindowtextNum füllen, in SetWindowtextNum wahrscheinlich besser ein sprintf (string, "%2d", number);
                // wenn die Zeit abgelaufen ist, KillTimer(hwnd,1); aufrufen 
    			break;
    		}
    ...
    }
    


  • Mein Timer funktioniert ja, nur wird SetWindowTextNum nicht aufgerufen bzw. schreibt nichts. Erst, wenn der Timer abgelaufen ist, wird geschrieben.

    http://img819.imageshack.us/img819/2783/83619360.png
    http://img3.imageshack.us/img3/9339/45016079.png

    Dazwischen bekomme ich keine Anzeigen.



  • Dazwischen bietest du Windows ja auch keine Gelegenheit, das Fenster neu zu zeichnen.



  • Ich kenne deine wait-Funktion nicht, vermutlich blockiert sie den Thread. Du könntest es mit UpdateWindow mit dem Handle auf dein Fenster probieren und vor allem einfach Sleep verwenden.

    Edit: Aber wie schon geschrieben, Windows-Timer können wegen des Schedulers ungenau sein, die Zeitspannen solltest du dir immer selber ausrechnen.



  • Danke.
    UpdateWindow hat geholfen.



  • Ok. Das hat geklappt, jetzt habe ich ein neues Problem.
    Solange ich das Fenster aktiv behalte, funktioniert alles wunderbar. Jedoch wenn ich es minimiere oder auf ein anderes Fenster klicke, frisst sich das Prog fest.



  • Wie hoch ist denn deine CPU-Auslastung des Prozesses?
    Wie schon geschrieben, das Beste wären entweder ein eigener Thread mit Sleep-Aufrufen oder Windows-Timer.



  • Ich habs mit Sleep un eigenem Thread.
    Da hab ich knapp 1500KB RAM die es braucht.

    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    #include <windowsx.h>
    #include <time.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <iostream>
    #include <Edit_Numbers.h>
    
    #include "resource.h"
    #include <mmsystem.h>
    
    void wait(int h, int m, int s, int ms)
    {
        //Wartefunktion, es wird die angegebene Zeit gewartet, die Funktion beendet sich wenn die zu wartende zeit vorüber ist.
        //create by: Tom Lambert
        //Originaldateiname: wait2.exe, wait2.pdb
        //Originalprojekt: wait2.sln, VS2010
        //Erstelldatum: 11.06.2011, Debugdatum: 11.06.2011
        clock_t zeit1, zeit2;
        float intervall = 0.001*CLOCKS_PER_SEC;
        bool flag = true;
    
        zeit1 = clock();
        zeit2 = clock()+h*3600000+m*60000+s*1000+ms;
    
        while(flag)
        {
            zeit1 = clock();
            //cout<<"Zeit1: "<<zeit1<<"\tZeit2: "<<zeit2<<endl;
            if(zeit1 >= zeit2)
                flag = false;
        }
    }
    
    BOOL play(char *name)
    {
      PlaySoundA(name, NULL, SND_FILENAME | SND_ASYNC);
      return 0;
    }
    
    BOOL pl_sound, waiting;
    int minutes_number, hours_number, seconds_number;
    HWND edit1, edit2, edit3;
    
    DWORD WINAPI SoundThreadFunction (LPVOID param)
    {
        pl_sound = TRUE;
        while(pl_sound == TRUE)
        {
            play("alarm.wav");
            wait(0,0,3,0);
        }
        return 0;
    }
    
    DWORD WINAPI WaitThreadFunction (LPVOID param)
    {
        waiting=TRUE;
        for (int i = hours_number * 60 * 60 + minutes_number * 60 + seconds_number; i > 0; i --)
        {
            wait (0,0,1,0);
            seconds_number --;
    
            if (seconds_number == -1)
            {
                minutes_number --;
                seconds_number = 59;
            }
    
            if (minutes_number == -1)
            {
                hours_number --;
                minutes_number = 59;
            }
    
            SetWindowTextNum (edit1, hours_number, 10);
            SetWindowTextNum (edit2, minutes_number, 10);
            SetWindowTextNum (edit3, seconds_number, 10);
    
        }
        waiting==FALSE;
    }
    
    HINSTANCE hInst;
    
    BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        switch(uMsg)
        {
        case WM_INITDIALOG:
            /*
             * TODO: Add code to initialize the dialog.
             */
            return TRUE;
    
        case WM_CLOSE:
            EndDialog(hwndDlg, 0);
            return TRUE;
    
        case WM_COMMAND:
            switch(LOWORD(wParam))
            {
                /*
                 * TODO: Add more control ID's, when needed.
                 */
            case IDC_BUTTON_QUIT:
                EndDialog(hwndDlg, 0);
                return TRUE;
    
            case IDC_BUTTON_START:
    
                //Handles erstellen
                HWND hours_insert = GetDlgItem (hwndDlg, IDC_EDIT_HOURS_INSERT);
                HWND hours_view = GetDlgItem (hwndDlg, IDC_EDIT_HOURS_VIEW);
                HWND minutes_insert = GetDlgItem (hwndDlg, IDC_EDIT_MINUTES_INSERT);
                HWND minutes_view = GetDlgItem (hwndDlg, IDC_EDIT_MINUTES_VIEW);
                HWND seconds_insert = GetDlgItem (hwndDlg, IDC_EDIT_SECONDS_INSERT);
                HWND seconds_view = GetDlgItem (hwndDlg, IDC_EDIT_SECONDS_VIEW);
                edit1 = hours_view;
                edit2 = minutes_view;
                edit3 = seconds_view;
    
                hours_number = GetWindowTextNum (hours_insert, 10);
                minutes_number = GetWindowTextNum (minutes_insert, 10);
                seconds_number = GetWindowTextNum (seconds_insert, 10);
    
                for (int i = hours_number * 60 * 60 + minutes_number * 60 + seconds_number; i > 0; i --)
                {
                    //wait (0,0,1,0);
                    Sleep (1000);
                    seconds_number --;
    
                    if (seconds_number == -1)
                    {
                        minutes_number --;
                        seconds_number = 59;
                    }
    
                    if (minutes_number == -1)
                    {
                        hours_number --;
                        minutes_number = 59;
                    }
    
                    SetWindowTextNum (hours_view, hours_number, 10);
                    SetWindowTextNum (minutes_view, minutes_number, 10);
                    SetWindowTextNum (seconds_view, seconds_number, 10);
                    UpdateWindow (hwndDlg);
    
                }
    
                HANDLE WaitThreadHandle = CreateThread(0, 0, WaitThreadFunction, 0, 0, 0);
    
                while (waiting==TRUE)
                {
                    UpdateWindow (hwndDlg);
                }
    
                HANDLE SoundThreadHandle = CreateThread(0, 0, SoundThreadFunction, 0, 0, 0);
                MessageBox(hwndDlg, "Die Zeit ist abgelaufen", "Time Alarm", MB_ICONWARNING);
                pl_sound = FALSE;
    
                return TRUE;
    
            }
        }
    
        return FALSE;
    }
    
    int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
    {
        hInst = hInstance;
    
        // The user interface is a modal dialog box
        return DialogBox(hInstance, MAKEINTRESOURCE(DLG_MAIN), NULL, (DLGPROC)DialogProc);
    }
    


  • Jetzt hast Du die Sachen aber gründlich vermischt.
    Du ruftst auf dem UI Thread Sleep() auf UND machst einen Thread der auch noch herunterzählt.

    ➡

    1. Benutze kein Update(..)
    2. Benutze Sleep() in der Thread Funktion
    3. Mache das Timer Zeugs im der DialogProc() weg - starte dort nur den Thread!
    4. Updates via PostMessage() (oder PostThreadMessage()) an den UI Thread!



  • Ok. Wir dumm von mir, dass ich dass vergessen habe aus dem Hauptthread rauszunehmen.
    Gut, doch wie funktioniert das mit dem PostMessage? Ich hab das noch nicht so durchschaut. Auch in der msdn binn ich nicht schlau geworden.



  • Also wenn das ein Lernprojekt ist: OK
    Sonst benutze SetTimer..) KillTimer(..) und die WM_TIMER, wäre irgendwie einfacher und besser:
    http://msdn.microsoft.com/en-us/library/ms644902(v=vs.85).aspx

    Dieser Vorschlag kam auch schon von anderen Postern.


Anmelden zum Antworten