Timer - jede sec. Fenster neu zeichnen
-
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 ?
-
Und WM_PAINT postet man ganz gewisslich nicht...
http://blog.m-ri.de/index.php/2007/12/24/die-unsitte-windows-interne-nachrichten-zu-versenden/
-
Das mit WM_PAINT hab ich schon geändert, aber es stand so in einem Tutorial dads ich verwendet habe, daher habe ich es übernommen.
Seit ich die Hintergrundfarbe nur noch alle 15min verändern lasse hört das fenster einfach nach ein paar sekunden auf neu zu zeichnen. Selbst wenn ich das neuzeichnen durch z.B. minimieren und dann wieder maximieren erzwinge wird das Fenster nicht neugezeichnet.
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { const RECT* rect; static RECT drawrect; int R, G, B; int a = 1; char Zeit[9]; char Stunden[3]; int Minuten; int Sekunden; char Minutenbuf[3]; char Sekundenbuf[3]; const char TextRoteZeit[] = "Nur ShortCourse"; const char TextWeisseZeit[] = "Nur Buggys & Truggys"; const char Kein18[] = "KEIN 1:8"; int Hintergrundfarbe; //1 = weiss | 2 = rot bool eineZeit = 0; char text[3]; RECT rechteck = {0, 0, 1280, 1024}; _strtime(Zeit); strncpy(Minutenbuf, Zeit + 3, 4); //die minuten isolieren 6,7 für Sekunden! Minuten = (Minutenbuf[0] - '0') * 10 + Minutenbuf[1] - '0'; //minuten in int umwandeln _strtime(Zeit); strncpy(Sekundenbuf, Zeit + 6,7); Sekunden = (Sekundenbuf[0] - '0') * 10 + Sekundenbuf[1] - '0'; switch (message) /* handle the messages */ { case WM_DESTROY: { KillTimer(hwnd, TimerID); //Timer wieder freimachen PostQuitMessage (0); /* send a WM_QUIT to the message queue */ break; } case WM_CREATE: { SetTimer(hwnd, TimerID, 100, NULL); //timer erstellen, 1000 = milliSekunden, NULL = WM_TIMER geht an hwnd wenn der timer zu ende ist } case WM_PAINT: { PAINTSTRUCT ps; HDC hDC; hDC = BeginPaint(hwnd, &ps); HDC hDCbuffer = CreateCompatibleDC(hDC); //zweites DC zum Double-buffering um das flackern beim zeichnen weg zu machen HBITMAP bufferBMP = CreateCompatibleBitmap(hDC, 1280, 1024); //eine bitmap für's double-buffering SelectObject(hDCbuffer, bufferBMP); //auch fürs double-buffering HFONT Schriftart = CreateFont(156, 91, 0, 00, //Schriftart erstellen und größe der Buchstaben festlegen FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, //normale Schriftqualität DEFAULT_PITCH | FF_ROMAN, //Times New Roman "Times New Roman"); HFONT kleineSchriftart = CreateFont(70, 40, 0, 00, //Schriftart erstellen und größe der Buchstaben festlegen FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, //normale Schriftqualität DEFAULT_PITCH | FF_ROMAN, //Times New Roman "Times New Roman"); { HBRUSH RechteckFarben = (HBRUSH)CreateSolidBrush(RGB(100, 100, 100)); //diese farbe wenn farbwechsel nicht funktioniert if(eineZeit == 1){ RechteckFarben = (HBRUSH)CreateSolidBrush(RGB(100, 100, 100)); SetBkColor(hDCbuffer, RGB(100,100,0)); //Hintergrundfarbe des Textes ändern!!! } else if(Minuten >= 0 && Minuten < 15){ RechteckFarben = (HBRUSH)CreateSolidBrush(RGB(255, 0, 0)); //RGB farben des fensters Hintergrundfarbe = 2; //1 = weiss | 2 = rot SetBkColor(hDCbuffer, RGB(255,0,0)); //Hintergrundfarbe des Textes ändern!!! } else if(Minuten >= 15 && Minuten < 30){ RechteckFarben = (HBRUSH)CreateSolidBrush(RGB(255, 255, 255)); //RGB farben des fensters Hintergrundfarbe = 1; //1 = weiss | 2 = rot SetBkColor(hDCbuffer, RGB(255,255,255)); //Hintergrundfarbe des Textes ändern!!! } else if(Minuten >= 30 && Minuten < 45){ RechteckFarben = (HBRUSH)CreateSolidBrush(RGB(255, 0, 0)); //RGB farben des fensters Hintergrundfarbe = 2; //1 = weiss | 2 = rot SetBkColor(hDCbuffer, RGB(255,0,0)); //Hintergrundfarbe des Textes ändern!!! } else if(Minuten >= 45){ RechteckFarben = (HBRUSH)CreateSolidBrush(RGB(255, 255, 255)); //RGB farben des fensters Hintergrundfarbe = 1; //1 = weiss | 2 = rot SetBkColor(hDCbuffer, RGB(255,255,255)); //Hintergrundfarbe des Textes ändern!!! } HBRUSH hOldBrush = (HBRUSH)SelectObject(hDC, CreateSolidBrush(RGB(100,220,120))); Rectangle( //rechteck hDCbuffer, //hdcbuffer fürs double-buffering | wenn kein double-buffering -> hDC 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 hDCbuffer, //hdcbuffer fürs double-buffering | wenn kein double-buffering -> hDC &rechteck, //rect-struktur des fensters RechteckFarben //HBRUSH strukture mit den farben ); DeleteObject(SelectObject(hDC, hOldBrush)); //Objekt löschen bevor mit SelectObject ein neues ausgewählt wird DeleteObject(SelectObject(hDC, RechteckFarben)); //Objekt löschen bevor mit SelectObject ein neues ausgewählt wird SelectObject(hDCbuffer,Schriftart); //schriftart auswählen die für TextOut usw. benutzt werden soll TextOut(hDCbuffer, 250, 240, Zeit, sizeof(Zeit)-1); //hdcbuffer fürs double-buffering | wenn kein double-buffering -> hDC DeleteObject(Schriftart); //Objekt wieder freigeben, für eine neue schriftart SelectObject(hDCbuffer,kleineSchriftart); //NEUE KLEINERE auswählen die für TextOut usw. benutzt werden soll if(Hintergrundfarbe == 1) { //1 = weiss | 2 = rot TextOut(hDCbuffer, 190, 420, TextWeisseZeit, sizeof(TextWeisseZeit)-1); } else if(Hintergrundfarbe == 2) { //1 = weiss | 2 = rot TextOut(hDCbuffer, 310, 420, TextRoteZeit, sizeof(TextRoteZeit)-1); } TextOut(hDCbuffer, 450, 490, Kein18, sizeof(Kein18)-1); DeleteObject(kleineSchriftart); //Objekt wieder freigeben } BitBlt(hDC, 0, 0, 1280, 1024, hDCbuffer, 0, 0, SRCCOPY); //buffer zeichnen, alten brush überzeichnen DeleteObject(SelectObject(hDC, bufferBMP)); ReleaseDC (hwnd, hDCbuffer); //DC wieder freigeben ReleaseDC(hwnd, hDC); //DC wieder freigeben EndPaint(hwnd, &ps); break; } case WM_TIMER: { InvalidateRect(hwnd,&rechteck,TRUE); if(Minuten == 00 || Minuten == 15 || Minuten == 30 || Minuten == 45){ if(Sekunden == 00){ mciSendString("open truckhupeNEU.mp3", NULL, 0, NULL); //MUSIKDATEI ÖFFNEN GEHT AUCH MIT VIDEOS mciSendString("play truckhupeNEU.mp3 wait", NULL, 0, NULL); // MUSIKDATEI ABSPIELEN mciSendString("close truckhupeNEU.mp3", NULL, 0, NULL); //MUSIKSATEI WIEDER SCHLIESSEN } } break; } case ID_1ZEIT: eineZeit = 1; break; case ID_2ZEITEN: break; case ID_3ZEITEN: break; case ID_VERSION: { MessageBox(hwnd,"This is a beta version," "please report all bugs!", "", MB_OK); default: /* for messages that we don't deal with */ return DefWindowProc (hwnd, message, wParam, lParam); } return 0; }