Timer - jede sec. Fenster neu zeichnen
-
Hallo, ich habe eine Win32 Anwendung bei der auf dem Bildschirm ein Countdown angezeigt werden soll. Damit der countdown aktuell bleibt muss ich dann jede sekunde das fenster neu zeichnen (das mach ich mit InvalidateRect()). Jetzt ist die Frage wie ich den countdown zum neu-zeichnen mache. Wenn ich aber eine schleife mache mit na wait() oder sleep() Funktion mache blockiert die die ganze zeit die nachrichten-abfrage
Außerdem soll von der Systemzeit ausgegangen werden, wie mach ich das?
-
SetTimer
-
Scheint bei mir nicht zu gehen. Erstmal dauert es ziemlich lange bis das erste mal aktualisiert wird und danach auch nur in unregelmäßigen abständen.
Hier mal mein code:
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { const UINT TimerID = 1; [...] SetTimer(hwnd, TimerID, 1000, NULL); [...] switch(message) { case WM_DESTROY: PostQuitMessage (0); /* send a WM_QUIT to the message queue */ break; case WM_TIMER: InvalidateRect(hwnd,NULL,TRUE); case WM_INITDIALOG: PostMessage(hwnd, WM_PAINT, 0,0); break; case WM_PAINT: { PAINTSTRUCT ps; HDC hDC; hDC = BeginPaint(hwnd, &ps); { RECT rechteck = {0, 0, 1280, 1024}; HBRUSH RechteckFarben = (HBRUSH)CreateSolidBrush(RGB(100, 100, 100)); //diese farbe wenn farbwechsel nicht funktioniert if(Sekunden >= 0 && Sekunden <= 15){ RechteckFarben = (HBRUSH)CreateSolidBrush(RGB(255, 0, 0)); //RGB farben des fensters neuHintergrundfarbe = 2; } else if(Sekunden > 15 && Sekunden <= 30){ RechteckFarben = (HBRUSH)CreateSolidBrush(RGB(255, 255, 255)); //RGB farben des fensters } else if(Sekunden > 30 && Sekunden <= 45){ RechteckFarben = (HBRUSH)CreateSolidBrush(RGB(255, 0, 0)); //RGB farben des fensters } else if(Sekunden > 45){ RechteckFarben = (HBRUSH)CreateSolidBrush(RGB(255, 255, 255)); //RGB farben des fensters neuHintergrundfarbe = 1; } HBRUSH hOldBrush = (HBRUSH)SelectObject(hDC, CreateSolidBrush(RGB(100,220,120))); Rectangle( //rechteck hDC, //devide context handle rechteck.left, //x-koordinaten der oberen linken ecke rechteck.top, //y-koordinaten der oberen linken ecke rechteck.right, //x-koordinaten der rechten unteren ecke rechteck.bottom //y-koordinaten der rechten unteren ecke ); FillRect( //rechteck einfärben hDC, //device context &rechteck, //rect-struktur des fensters RechteckFarben //HBRUSH strukture mit den farben ); TextOut(hDC, 200, 100, Zeit, sizeof(Zeit)-1); drawrect.left = 50; //x-koordinaten der oberen linken ecke drawrect.top = 50; //y-koordinaten der oberen linken ecke drawrect.right = 700; //x-koordinaten der rechten unteren ecke drawrect.bottom = 700; //y-koordinaten der rechten unteren ecke DrawText( hDC, drawnText, sizeof(drawnText)-1, &drawrect, DT_CENTER); DeleteObject(SelectObject(hDC, hOldBrush)); } ReleaseDC(hwnd, hDC); EndPaint(hwnd, &ps); break; } [...] KillTimer(hwnd, TimerID);
-
case WM_TIMER: InvalidateRect(hwnd,NULL,TRUE); return 0; // sonst gehts weiter in den nächsten Zweig case WM_INITDIALOG: UpdateWindow(hwnd); // wenn dann UpdateWindow, sollte aber auch unnötig sein return 0;
Und den ReleaseDC-Aufruf im WM_PAINT-Zweig entfernen.
Achja,
hOldBrush
sollte vom Typ HGDIOBJ sein, dann braucht's auch keinen Cast.
-
Wo bekommst du "Sekunden" her?
Holst du das vom System, oder zählst du irgendwie mit?
Mitzählen wäre nämlich weniger empfehlenswert.
-
Den Code habe ich mir jetzt auch gar nicht genauer angeschaut (hat hustbär ja schon), aber das Memoryleak im Paintzweig ist schon auffällig.
Du könntest den DC-Brsuh in den Kontext einwählen und dann nur dessen Farbe mit SetDCBrushColor ändern.
-
Ok, mit deinen Änderungen und wenn ich SetTimer(); hinter DispatchMessage(); packe läuft der Timer sauber genug für meine Bedürfnisse.
while (GetMessage (&messages, NULL, 0, 0)) { /* Translate virtual-key messages into character messages */ TranslateMessage(&messages); /* Send message to WindowProcedure */ DispatchMessage(&messages); SetTimer(hwnd, TimerID, 100, NULL); //timer erstellen, 1000 = millisekunden, NULL = WM_TIMER geht an hwnd wenn der timer zu ende ist /* Run the message loop. It will run until GetMessage() returns 0 */ }
Aber beim neuzeichnen des Fensters hab ich immer so einen blöden aufblinkenden balken, vermutlich liegt es an dem rect, das dann jedesmal auch neugezeichnet werden muss. Kennt jmd. eine möglichkeit das zu vermeiden oder zu umgehen (ich benutze das Rect quasi als Hintergrund um alle 15sec die Hintergrundfarbe zu ändern)
-
Aktiviere den Timer bitte in WM_INITDIALOG...
Die Msg-Schleife solltest Du nicht verändern!
-
Sekunden ist ein integer und den hab ich aus der systemzeit "isoliert". D.h. Bei 12:31:07 uhr wäre der wert 07.
@jochen: werde icj morgen mal ausprobieren.
@Thogrim: was ist memoryleak? Und wie genau meinst du das mit setdcbrushcolor()?Mfg Cody227
-
@Cody227
Ein Leak ist, wenn du was erzeugst und dann "vergisst".
Das wird dann nie wieder zerstört. D.h. du erzeugst einen Müllberg der grösser und grösser wird. Irgendwann ist alles voll (z.B. kein Speicher mehr verfügbar), und dann machts Peng!.In deinem Code erzeugst du haufenweise Brushes (CreateSolidBrush) die nie wieder freigegeben werden (DeleteObject).
-
memoryleak = lochfras in der birne oder alzheimer...
wie hustbaer schon sagt, du erzeugst löcher in deinem speicher die du nicht mehr beschreiben kannst und die weiterhin bestehn bleiben.
-
Hört sich ja übel an. Aber den speicher bekomm ich ja beim neustarten bestimmt wieder.
Hat noch jmd eine idee wie ich die hässlichen striche beim neuzeichnen weg machen kann?
//EDIT: wenn ich SetTimer() bei WM_INITDIALOG rein packe startet der timer nicht.
//EDIT2: SetDCBrushColor() funktioniert auch nicht. Ich habe alle nötigen Dateien inkludiert (die die in der msdk angegeben sind) aber ich bekomme trotzdem den fehler "SetDCBrushColor' undeclared (first use this function)". Dieses Problem scheinen auch andere Leute zu haben, aber ich habe noch keine Lösung gefunden
-
Aber den speicher bekomm ich ja beim neustarten bestimmt wieder
du hast noch nicht ganz verstanden worauf das hinausläuft...
klar bekommst du den speicher sogar beim neustart deines programms wieder (mittlerweile ist windows so gut)
aber dir scheint nicht klar zu sein, das dadurch fehler im speicher innerhalb deines programmes passieren. was zum absturz bzw. seltsamen verhalten deines programes führt.
-
Das problem mit den streifen/flackern hab ich jetzt mit double-buffering gelöst, Aber SetTimer() scheint nirgendwo anders zu funktionieren als in der message-schleife wie ich es am anfang schon hatte
-
Weil du ein vermutlich ein Fenster erzeugt hast und und somit WM_CREATE als erste Nachricht ankommt - WM_INITDIALOG wird, wie der Name vermuten lässt, nur Dialogen zugesandt.
SetDCBrushColor ist erst ab Win2000 verfügbar, vor dem Inludieren von windows.h müsstest du daher _WIN32_WINNT größer oder gleich 0x0500 definieren.Und ich hoffe doch, dass das Zeichnen nun außerhalb von WM_PAINT geschieht - ich habe es schon so oft gesehen, dass Double-Buffering verwendet wurde und dass alle Maloperationen immer noch in diesem Zweig durchgeführt wurden...
-
Ich dachte man zeichnet nur innerhalb von wm_paint? Aber es funktioniert trotzdem einwandfrei. SetTimer() in wm_create zu packen hab ich auch schon probiert, hat nicht funktioniert.
-
Weiss jemand wie ich formatierten Text richtig groß anzeigen kann? Also mit richtig großer Schriftgröße, andere Textfarbe und ohne die weiße Hinterlegung wie bei Funktionen wie TextOut()?
-
ich würde mich damit mal auseinander setzen
-
Hab mir gestern schon das (englische) Kapitel über fonts durch gelesen. Dadurch konnte ich dann auch die Schrift größer machen. Leider ist da aber immernoch diese hässliche weiße Hinterlegung der Schrift. Möglicherweise könnte ich das mit einer Vector-Schrift umgehen, aber leider hab ich dazu noch nichts bei google gefunden
-
Hab noch ein ziemlich gravierendes Problem: Mein programm funktioniert nicht auf einem 2. Bildschirm, d.h. es wird dort nicht mehr neugezeichnet.
woran kann das liegen?
-
Jochen Kalmbach schrieb:
Aktiviere den Timer bitte in WM_INITDIALOG...
Die Msg-Schleife solltest Du nicht verändern!so ist es.
Und ausserdem scheint auch KillTimer an der falschen Stelle zu sein ?