aLeXanDer.. Geschrieben 17. Dezember 2007 Geschrieben 17. Dezember 2007 Hallo Community, Ich bin gerade drüber einen Wecker in Windows zu programmieren. Man kann entweder bestimmte Tage angeben die die dann für jede Woche gelten oder man kan ein bestimmtes Datum eingeben. Dazu noch eine Uhrzeit und einen Text der dann Ausgegeben werden soll. Das ganze Übertrage ich in ein StringGrid und dann speicher ich es per StringList in eine txt. Beim nächsten Start werden die Vorhandenen Wecktermine wieder in das StringGrid geladen. Außerdem ist dem Programm noch in einem Label die aktuelle Uhrzeit und das Datum mitgegeben. Die Uhrzeit hole ich über TDateTime = Now() über Multithreading; So meine Frage ist nun , Der Benutzer hat seine Daten eingetippt und abgespeichert. Wie frage ich das ab? Ich denke das ich noch einen weiteren Thread erstellen muss und dort die Abfrage routine definieren muss. Die Abfrage ist dann eine for schleife die jede Sekunde oder eventuell Minute die Now() mit den einzelnen Werten aus der Liste vergleicht. wenn einer Identisch ist gibts ne Meldung oder nen Alarm. Sind meine Überlegungen bezüglich des alamierens meines Weckers richtig? Oder gibt es einen einfacheren Weg dann den Alarm auszulösen zu dem vorgegebenen Zeitpunkt? Mfg Alex Zitieren
U-- °LoneWolf° Geschrieben 17. Dezember 2007 Geschrieben 17. Dezember 2007 Hi für sowas hast du eine TImer Komponente. Dieser kannst du mit geben das alle X Sec. eine AKtion ausgeführt wird. Man spricht auch von Ticks und On_Tick Zitieren
aLeXanDer.. Geschrieben 17. Dezember 2007 Autor Geschrieben 17. Dezember 2007 Alle X Sec ist ja eher nicht so gut. Ich speichere ja Datum , bzw. Tag, und Zeit ab. Also muss ich ja erst den Tag abgleichen bzw. Datum (Sind 2 verschiedene Sachen in meinem Programm) und dann die Zeit. Da nützt mir die Funktion die du von Timer beschrieben hast denke ich mal nichts. Muss ich es wohl doch über meinen Ansatz machen?! Zitieren
Klotzkopp Geschrieben 17. Dezember 2007 Geschrieben 17. Dezember 2007 Alle X Sec ist ja eher nicht so gut.Wieso nicht? X kann ja auch 1 sein. Muss ich es wohl doch über meinen Ansatz machen?!Nein. Ein Timer reicht völlig aus. Du kannst den Timer ggf. auch flexibel halten, d.h. wenn der nächste Alarmzeitpunkt weit entfernt ist, das Timerintervall raufsetzen. Zitieren
aLeXanDer.. Geschrieben 17. Dezember 2007 Autor Geschrieben 17. Dezember 2007 Intervall heißt doch er prüft in diesem Intervall , also dieser Zeiteinheit die man ihm da mitgibt richtig?! Wie ist das dann, wenn ich heute sage er soll am 2.2.08 um 12 Uhr eine Erinnerung ausgeben. Wie läuft das dann ab?! Steig irgendwie nicht in die Funktionsweiße der Komponente ein. Habs bis jetzt so umgesetzt wie ich meinte, mit noch nem Thread und einer Schleife die dauernd die abgespeicherten Daten durchgeht und mit Datum und Uhrzeit abgleicht. Geht auch , brauch nur noch eine Idee wie ich mit dem Datum den Tag rausfinde. Praktisch ob der 19.12.07 ein Donnerstag is oder ein Mittwoch. Das schöne ist ja das immer mehr Wege zum Ziel führen Zitieren
U-- °LoneWolf° Geschrieben 17. Dezember 2007 Geschrieben 17. Dezember 2007 Also den Wochentag kannst du ganz einfach berechnen lassen in dem du die anzahl Tage vom z.B. 03.12.2007 bis zum 19.12.2007 berechnest und dann das ergebniss durch 7 teilst. Wegen dem Timer naja ganz einfach der Timer löst nach ablauf eines Interfalls einen Event aus. in diesem prüfts du dann einfach ob ein eventausgelöst werden muss oder nicht. Das macht das ganze einfacher und ist vermutlich nicht so belastent wie ein Thread der in einer endlosschleife läuft. Achja und zudem kannst du z.B. wie klotzkop schon geschrieben hat das Intervall so wählen das der TImer erst beim nächsten event auslöst. Zitieren
aLeXanDer.. Geschrieben 19. Dezember 2007 Autor Geschrieben 19. Dezember 2007 Das mit dem Wochentag ging einfacher gab von der TDateTime Komponente den Befehl DayOfWeek(); =) So nun hab ich meinen Wecker in die Trayleiste versteckt und Prophisorisch, ihm ein Windows Standard Icon verpasst und zwar weil ich es nicht auf die Reihe Bringe ihm das in dem verzeichnis liegende .ico zu nehmen. LRESULT IconDrawItem(LPDRAWITEMSTRUCT lpdi) { HINSTANCE hInst; HICON hIcon; hIcon = (HICON)LoadImage(hInst, "Calendar.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE); [I]richtig? und weiter ?[/I] // return [I]???[/I] } Muss hier ja einen Wert mitgeben denn ich in dieser Funktion bool __fastcall TForm1::BarMessage(DWORD dwMessage) { NOTIFYICONDATA tnd; PSTR pszTip; pszTip = GetTip(); tnd.cbSize = sizeof(NOTIFYICONDATA); tnd.hWnd = Handle; tnd.uID = IDC_MYICON; tnd.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; tnd.uCallbackMessage = MYWM_NOTIFY; if (dwMessage == NIM_MODIFY) { tnd.hIcon = //Anderes ICON LADEN?? if (pszTip) lstrcpyn(tnd.szTip, pszTip, sizeof(tnd.szTip)); else tnd.szTip[0] = 0; } else { tnd.hIcon = LoadIcon(NULL,IDI_WINLOGO); // Standard Windows ICON LADEN tnd.szTip[0] = 0; } return (Shell_NotifyIcon(dwMessage, &tnd)); } Ich komm nicht drauf ist im ersten ein Fehler? Wie ruf ich das Icon denn dann auf?! Hab im i-net ähnliches gefunden aber nichts was mit weitergeholfen hätte Zitieren
Klotzkopp Geschrieben 19. Dezember 2007 Geschrieben 19. Dezember 2007 Du solltest hInst schon noch initialisieren. Da steht nicht automatisch der richtige Wert drin. Zitieren
aLeXanDer.. Geschrieben 19. Dezember 2007 Autor Geschrieben 19. Dezember 2007 HINSTANCE hInst; Mit was muss man hInst denn initialisieren Finde in der Hilfe nichts darüber. Zitieren
Klotzkopp Geschrieben 19. Dezember 2007 Geschrieben 19. Dezember 2007 Finde in der Hilfe nichts darüber.Wo hast du denn gesucht? LoadImage Function () Da steht: hinst ... To load a stand-alone resource (icon, cursor, or bitmap file)—for example, c:\myimage.bmp—set this parameter to NULL. Zitieren
aLeXanDer.. Geschrieben 19. Dezember 2007 Autor Geschrieben 19. Dezember 2007 BorlandBuilder 5 ->Tools->Hilfe Laut dieser Hilfe muss ich jetzt hInst NULL setzen verstehe ich das richtig?! Und wie übergeb ich dann den Wert an die andere Funktion?! Zitieren
aLeXanDer.. Geschrieben 20. Dezember 2007 Autor Geschrieben 20. Dezember 2007 Das mit dem Icon habe ich immernoch nicht hinbekommen. Leider Zudem hab ich auch noch ein neues , wie ich finde komisches, Problem. Das Problem ist , ich gebe meinem Wecker eine Alarmzeit. Ist die Alarmzeit erreicht und der Wecker ist gerade im Tray , erscheint einwandfrei die Message die der User eingegeben hat. Ist der Wecker aber geöffnet , also der User sieht in gerade an oder so. Kommt ein Fehler "Leinwand/Bild erlaubt keine Zeichen" und ich werde im Code auf diese Zeile im meinem PrüfThread hingewiesen. PrüfThread = Er durchläuft mit der Zeit die Weckerdaten und wenn was übereinstimmt gibt er laut =) Form1->Meldungausgeben(Form1->StringGrid1->Cells[4][i]); in Meldungausgeben ist folgendes: void __fastcall TForm1::Meldungausgeben(AnsiString text) { Beep(37,200); Beep(250,200); ShowMessage(text); } Aber Warum geht es dann wenn der Wecker im Tray ist, da rufe ich ja dieselbe Routine auf?! Aber es wird schon noch mhh komischer. Das passiert wenn ich das Projekt mit dem BorlandBuilder kompiliere. Wenn ich aber die fertige Exe benutze und habe dann den Wecker aktiv, dann erhalte ich ohne Fehler die Message. ??? Achjah und dann noch ein Unterschied , wenn ich mit Borland kompeliere und Beende das Programm passiert nichts. Starte ich die Exe und beende dann das Programm erhalte ich : "Fehler in Anwendung" Die Anweisung in "0x400bf197" verweist auf Speicher in "0x000002c0". Der Vorgang "read" konnte nicht auf dem Speicher durchgeführt werden. Klicken Sie "OK", um das Programm zu beenden. "Abrechen", um zu debuggen. Hab schon danach gegoogelt und viele schreiben das sie das auch bei Programmen wie Mozilla und Firebird oder irgend einer Abspielsoftware erhalten. Hab gedacht es ist weil ich eine Schriftart mit AddFontResourceEx einbinde und ich sie danach wieder Removen will, das er das nicht packt, aber auch als ich das auskommentiert habe , kam die Meldung. Den WeckerCode zu posten ist wohl ein bisschen viel, sag ich mal. Wenn mir jemand helfen kann, oder Rat weiß und dazu mal etwas vom Code sehen muss,will, je nachdem, einfach schreiben. Mfg Alex Zitieren
aLeXanDer.. Geschrieben 20. Dezember 2007 Autor Geschrieben 20. Dezember 2007 Ok das mit dem Icon im sysTray habe ich nun doch gelöst Hab zwar länger gebraucht aber nun gehts =) Danke Klotzkopp Aber der die anderen Fehler sind noch da. Zitieren
Klotzkopp Geschrieben 20. Dezember 2007 Geschrieben 20. Dezember 2007 PrüfThread = Er durchläuft mit der Zeit die Weckerdaten und wenn was übereinstimmt gibt er laut =) Form1->Meldungausgeben(Form1->StringGrid1->Cells[4][i]);Greift dein "Prüfthread" etwa direkt auf die Fensterobjekte zu? Das ist nicht erlaubt. Nur der Thread, der ein Fenster erzeugt hat, darf darauf zugreifen. Starte ich die Exe und beende dann das Programm erhalte ich : Die Anweisung in "0x400bf197" verweist auf Speicher in "0x000002c0". Hab schon danach gegoogelt und viele schreiben das sie das auch bei Programmen wie Mozilla und Firebird oder irgend einer Abspielsoftware erhalten.Das ist vermutlich ein Lesezugriff über einen Nullzeiger. Das ist ein sehr allgemeiner Programmfehler, und hat mit der Art des Programms wenig zu tun. Das liegt wahrscheinlich auch daran, dass du in deinem Thread Sachen machst, die du nicht machen darfst. Ich hatte dir gleich zu einem Timer geraten, da hättest du solche Probleme nicht. Zitieren
aLeXanDer.. Geschrieben 21. Dezember 2007 Autor Geschrieben 21. Dezember 2007 Ja Form1->Meldungausgeben(Form1->StringGrid1->Cells[4][i]); steht in Unit2 und Unit1 hat das Formular. deswegen jah Form1->Meldungsausgeben... Wenn man das nicht darf, wie teil ich dann mit , das der Weckertermin erreicht ist? Man kann ja auch mal andere Möglichkeiten ausprobieren, ob die gut sind sieht man erst nachdem man sie getestet hat. Jetzt weiß ich das du Recht hast. Pardon Zitieren
aLeXanDer.. Geschrieben 21. Dezember 2007 Autor Geschrieben 21. Dezember 2007 Ich will jetzt meine Entschuldigung nicht zurücknehmen aber ich hab auch das Speicherproblem gelöst Musste einfach die Reihenfolge in der ich die Threads beende umstellen und einen kleinen Wait einbauen. Zitieren
Klotzkopp Geschrieben 21. Dezember 2007 Geschrieben 21. Dezember 2007 Ich bezweifile, dass du das Problem gelöst hast. Es tritt nur nicht mehr (oder nicht mehr so häufig) auf. Man könnte sagen, du hast es schwieriger reproduzierbar gemacht. Threadsynchonisierung mittels Warten ist keine saubere Lösung. Zitieren
aLeXanDer.. Geschrieben 21. Dezember 2007 Autor Geschrieben 21. Dezember 2007 Auch nicht wenn ich sage Er soll warten bis der eine Thread in seiner Schlefie wieder oben angelang tist und iohn dann beenden ? ist doch sauber gelöst?! Zitieren
Kael_Uka Geschrieben 21. Dezember 2007 Geschrieben 21. Dezember 2007 Ich hab mal eine ganz andere Frage: Wie sieht es jetzt eigentlich mit der Performance aus? Braucht dein Programm nicht ziemlich viel Rechenkapazität? Zitieren
aLeXanDer.. Geschrieben 21. Dezember 2007 Autor Geschrieben 21. Dezember 2007 Ja die Auslastung ist bei 100% Werd es über Weihnachten wohl auf einen Timer umschreiben. SchischaSchade. Halt Hab ne Auslastung von 16% hab vergessen wieder was zu entkommentieren Zitieren
Kael_Uka Geschrieben 21. Dezember 2007 Geschrieben 21. Dezember 2007 Ist trotzdem ein bisschen viel. Ich hab mal unter c# ein kleines Countdownprogramm geschrieben, welches auch immer auf die aktuelle Zeit zurückgreift. Hab den Timerintervall auf 1 Sekunde gesetzt. Die Auslastung liegt bei 2%. Mir ist bewußt, dass der Vergleich hinkt, da wir unterschiedliche Rechner haben, trotzdem behaupte ich das dein Programm 4 mal "schneller" / performanter wird. Ist nur eine Behauptung. Beweisen oder garantieren kann ich das nicht. Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.