Frage zu Timer



  • Hi,

    wollte ein Programm schreiben, dass eine Eingabe des Benutzers nach ca. 10sek. gelöscht wird; dazu habe ich nach timer gegooglet, nur da wird immer von milisekundenbereich geredet und dass das mit Windows ein Problem darstellt.

    Benötige ja lediglich einen timer in sekundenschritte, der dann das ereigniss auslöst, die eingegeben Daten von der konsole zu löschen;

    vielleicht könnt ihr mir weiterhelfen 🙂

    gruß



  • Das folgende Progrämmchen löscht den Bildschirm 5 Sekunden nachdem eine Eingabe gemacht wurde, Beendigung durch Eingabe von "exit".

    #include <windows.h>
    #include <process.h>
    #include <iostream>
    #include <string>
    
    //Cursor positionieren
    void SetCursorPosition(int x, int y)
    {
        COORD pos = {x, y};
    
        SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
    }
    
    //Konsolenbildschirm löschen
    void ClearScreen(void)
    {
        CONSOLE_SCREEN_BUFFER_INFO csbi;
        COORD target = {0, 0};
        DWORD written;
    
        GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
        FillConsoleOutputCharacter(GetStdHandle(STD_OUTPUT_HANDLE), ' ',
                                                csbi.dwSize.X * csbi.dwSize.Y,
                                                target, &written);
        FillConsoleOutputAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7,
                                                csbi.dwSize.X * csbi.dwSize.Y,
                                                target, &written);
    }
    
    // Funktion, die beim Timeout ausgeführt werden soll
    void CALLBACK TimeOut(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
    {
        ClearScreen();
        SetCursorPosition(0, 0);
        PostThreadMessage(GetCurrentThreadId(), WM_QUIT, 0, 0);
    } 
    
    DWORD WINAPI MyThread (void * Param)
    {
       MSG msg;
    
       UINT timerID; // ID für Timer;
    
    	timerID = SetTimer(NULL,0,(UINT)5000,&(TIMERPROC)TimeOut); // Timer setzen auf 5 sec
    
       while (GetMessage (&msg, NULL, 0, 0))
       {  
          DispatchMessage(&msg);
       }
    
    	KillTimer(NULL, timerID);
       return 0;
    }
    
    void main(void)
    {
       HANDLE hThread = 0;
    
    	using namespace std;
    
    	string in;
    
    	getline(cin, in);
    	while(in != "exit")
    	{
    		cout << "\n\nDu hast eingegeben: " << in << "\n\n";
    		CloseHandle(hThread);
          hThread = CreateThread(NULL, 0, MyThread, NULL, 0, 0);
          getline(cin, in);
       }
    
       WaitForSingleObject(hThread, INFINITE);
    
       CloseHandle(hThread);
    }
    


  • super, genau das was ich suche ^^

    da der quellcode im moment meinen programmtechnischen horizont überschreitet, frage ich ob dieser code hier:

    // Funktion, die beim Timeout ausgeführt werden soll 
    void CALLBACK TimeOut(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) 
    { 
        ClearScreen(); 
        SetCursorPosition(0, 0); 
        PostThreadMessage(GetCurrentThreadId(), WM_QUIT, 0, 0); 
    } 
    
    DWORD WINAPI MyThread (void * Param) 
    { 
       MSG msg; 
    
       UINT timerID; // ID für Timer; 
    
        timerID = SetTimer(NULL,0,(UINT)5000,&(TIMERPROC)TimeOut); // Timer setzen auf 5 sec 
    
       while (GetMessage (&msg, NULL, 0, 0)) 
       {   
          DispatchMessage(&msg); 
       } 
    
        KillTimer(NULL, timerID); 
       return 0; 
    }
    

    ausreichend ist, um das gewünschte Ergebnis zu erzielen ??

    (denke jetzt eher nicht, da ich anduaern diese Fehlermeldung bekomme beim Erstellen:

    Fehler1: error C2601: 'TimeOut': Lokale Funktionsdefinitionen sind unzulässig
    Fehler 2 error C2601: 'MyThread': Lokale Funktionsdefinitionen sind unzulässig
    Fehler 4 error C3861: "ClearScreen": Bezeichner wurde nicht gefunden.
    Fehler 5 error C3861: "SetCursorPosition": Bezeichner wurde nicht gefunden.
    Fehler 6 error C2065: 'TimeOut': nichtdeklarierter Bezeichner ;

    verwende aber auch die gleichen Header wie in deinen programm auch.. 😕 😕

    gruß



  • Die ersten beiden Meldungen sehen so aus, als hättest du die Funktionen im Inneren deiner main() definiert - sowas ist in C++ nicht erlaubt. Die dritte und vierte Meldung kommt von einer vergessenen Funktion aus Belli's Beispielcode.



  • ah, alles klar danke für den hinweis 🙂

    weißt du was er denn vergessen hat ??



  • DarkChip schrieb:

    weißt du was er denn vergessen hat ??

    Nicht er, du hast beim Abschreiben die beiden vom Compiler genannten Funktionen nicht mit übernommen (Zeile 6 bis 28).



  • Mhm ...
    also Fehler 1 und 2 klingen, als ob Du so etwas gemacht hättest:

    int main()
    {
        void CALLBACK TimeOut(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
        {
            ClearScreen();
            SetCursorPosition(0, 0);
            PostThreadMessage(GetCurrentThreadId(), WM_QUIT, 0, 0);
        }
    ...
    }
    

    Das geht natürlich nicht, Funktionen dürfen nicht innerhalb anderer Funktionen definiert werden.
    Fehler 3 und 4 resultieren wohl daher, dass Du die Funktionen ClearScreen und SetCursorPosition in Deinem Code nicht mehr hast, TimeOut sie aber aufrufen möchte ...
    Fehler 5 könnte mit Fehler 1 und 2 zusammenhängen, wenn ich richtig geraten habe, hast Du die Funktion TimeOut nicht korrekt (ausserhalb aller anderen Funktionen) definiert, und die Adresse kann deshalb nicht gefunden werden ...
    Zu meinem Quellcode:
    Die Funktionen ClearScreen und SetCursorPosition machen einfach das, was der Name vermuten lässt: eine löscht die Konsole, die andere setzt den Cursor auf die gewünschte Position.
    Die Funktion TimeOut ist die Funktion, die vom Windowstimer aufgerufen werden soll, wenn die Timeout-Zeit erreicht wird.
    Da die Windowstimerfunktion nur in Programmen funktioniert, die eine Messageloop (zu Deutsch Nachrichtenschleife) haben, Konsolenprogramme aber im Normalfall keine Nachrichtenschleife besitzen, habe ich eine Threadfunktion MyThread eingebaut, die eine Nachrichtenschleife (GetMessage) startet.

    In der main-Funktion wird nun nach jeder Eingabe (außer "exit") ein Thread gestartet (CreateThread), der einen Timer setzt. Dieser Timer läuft nach 5000 Millisekunden ab und ruft dann die Funktion TimeOut auf. Diese wiederum löscht jetzt die Konsole (ClearScreen) und setzt den Cursor in die obere linke Ecke (SetCursorPosition), dann sendet sie dem Thread die WM-QUIT - Nachricht, die bewirkt, dass der Thread seine Nachrichtenschleife beendet. Dieser zerstört nun den Timer (KillTimer) und beendet sich.

    In main wird immer das Handle auf den letzten gestarteten Thread gespeichert (hThread), damit vor Beendigung des Programmes auf das Ende des Threads gewartet werden kann (WaitForSingleObject). Da alle Threads nach einmaligem Ablauf des Timers beendet werden, kann man davon ausgehen, dass im Normalfall alle Threads beendet sind, wenn der zuletzt gestartete beendet ist.



  • DarkChip schrieb:

    weißt du was er denn vergessen hat ??

    👍



  • sorry, mein Fehler *rot werd*

    danke auch für die tolle erklärung, kann damit auch was anfangen;

    hab die funktionen nun ausserhalb der main eingefügt, und er gibt nur einen Fehler aus:

    timerID = SetTimer(NULL,0,(UINT)2000,&(TIMERPROC)TimeOut); // Timer setzen auf 5 sec

    1 IntelliSense: Der Ausdruck muss ein lvalue oder ein Funktionskennzeichner sein.

    Programm wird aber dabei ausgeführt, von daher kann das jetzt nicht SOO schlimm sein, oder ??

    // Edit:

    Und - jetzt eine ganz saublöde frage noch:

    wie trage ich das ganze nun in meinen quellcode ein ?? 😃
    gruß

    gruß



  • DarkChip schrieb:

    wie trage ich das ganze nun in meinen quellcode ein ??

    Mal sehen, um es möglichst einfach zu machen:
    Kopier Dir den Code ohne die main - Funktion vor Deine eigene main - Funktion.
    Ändere die Signatur der Funktion MyThread, so dass sie so aussieht:

    void MyThread (void * Param)
    

    und wirf die return - Anweisung am Funktionsende hinaus.
    Dann kannst Du sie anders starten und brauchst Dich nicht um das HANDLE zu kümmern.
    Wann immer Du nun in Deinem Programm willst, dass 5 Sekunden (die Zeit kannst Du natürlich in MyThread nach Belieben selbst ändern) später die Konsole gelöscht wird, fügst Du

    ...
    _beginthread(MyThread, 0, 0);
    ...
    

    ein. Dein Programm läuft danach ganz normal weiter, aber 5 Sekunden später wird die Konsole gelöscht.
    Und nun geh ich ins Bett, viel Erfolg!



  • super, vielen Dank jetzt funzt 😃

    das mit den zu Bett gehen überlege ich mir noch 🙂


Anmelden zum Antworten