|
![]() |
|
Registriert seit: 13. Mär 2007 130 Beiträge |
#1
Ich suche nach Programmideen, nachdem ich hier im Forum bereits eine Warenberechnung (Programm Waren) und den Verkauf von Kinokarten (Programm Kinokarten) vorgestellt habe. Bei der Realisierung dieser Programme konnte ich eine Reihe von Anregungen umsetzen und habe dabei viel dazugelernt.
Ich will keineswegs auf der Stelle treten. [...] Ich werde also weitergrübeln und die Foren durchstreifen. Wenn jemand eine Idee haben solle, wäre ich dafür dankbar. ![]() ![]() Ich kenne jetzt nicht so genau deine Aufgabenpräferenz, aber vielleicht reizt dich das ja? Besonders das Erstellen und Lösen solcher Sudokus dem Computer beizubringen bringt dich vielleicht weiter? Brighty
Do you have the email of god??? --- I have to tell him that I'm happy to be born!
|
![]() |
Registriert seit: 1. Mai 2016 Ort: Berlin 419 Beiträge Delphi 10.2 Tokyo Professional |
#2
nun habe ich auch über einen längeren Zeitraum die Zeitdauer der Ausführung des Programmteils gemessen und stets den Wert 0 ms erhalten.
Nehmen wir mal Dein Beispiel mit einer Zeitdauer von angenommen 15 ms für die Programmausführung. Dann müsste also das Intervall auf 985 ms gesetzt werden, damit dann genau zur neuen sec. der neue Ablauf der Bestimmung der roem. Zahlen auf dem Turm neu beginnen kann? Sehe ich das so richtig? ![]() Ich habe mit 2 Methoden die Messung vorgenommen und immer nur 0 ms erhalten. Somit kann ich also kein Intervall setzen oder? Anbei das Beispiel für die Messung mit einer der beiden Methoden:
Delphi-Quellcode:
procedure TForm1.Timer2Timer(Sender: TObject); //Messung Intervall
var freq: Int64; startTime: Int64; endTime: Int64; Present: TDateTime; Year, Month, Day, Hour, Min, Sec, MSec: Word; Zeit : String; begin timer2.Enabled:=false; QueryPerformanceFrequency(freq); QueryPerformanceCounter(startTime); Present:= Now; SysUtils.DecodeDate(Present, Year, Month, Day); Label1.Caption := 'Der heutige Tag ist der ' + Dezinroem(IntToStr(Day)) + ' des '+Dezinroem(inttoStr(Month)) +'. Monates ' + ' des Jahres ' + DezinRoem(IntToStr(Year)); SysUtils.DecodeTime(Present, Hour, Min, Sec, MSec); Label2.Caption := DezInRoem(inttostr(Hour))+ ' Stunden, '+DezInRoem(inttostr(Min))+' Minuten und ' +DezinRoem(inttostr(Sec))+' Sekunden und '+DezinRoem(inttostr(MSec)) +' Milisekunden'; Label4.Caption:=DezInRoem(inttostr(Hour)); Label5.caption:=DezInRoem(inttostr(Min)); Label6.caption:=DezInRoem(inttostr(Sec)); Label7.caption:=DezInRoem(inttostr(mSec)); Zeit:=timeToStr(Time); Panel1.Caption:=Zeit; // Panel1.Caption:=TimeToStr(Time); StatusBar1.Panels[0].Text:=TimeToStr(Time); StatusBar1.Panels[1].Text:=FormatDateTime('"Heute ist "dddd," der "d.mmmm yyyy"',Date); DecodeTime(Time, Hour, Min, Sec, mSec); Trackbar1.Position:=Sec; QueryPerformanceCounter(endTime); timer2.Enabled:=true; ShowMessage('Die Routine benötigte etwa ' + IntToStr((endTime - startTime) * 1000 div freq) + ' ms'); end;
Norbert
|
![]() |
nahpets
(Gast)
n/a Beiträge |
#3
Du hast da wohl einen schnelleren Rechner als ich.
Zu Deinem ![]() Mess' bitte noch einmal, aber mit anderen Bedingungen. Setze die Priorität der Uhr (im Taskmanager) mal auf den niedrigstmöglichen Wert. Starte einen anderen Prozess (oder mehrere), von denen Du weißt, das richtig Systemlast erzeugt wird, setze deren Priorität eventuell auf Hoch, bei Echtzeit kann es sein, dass Du Windows nicht mehr so recht bedienen kannst. Prüfe dann, ob die Uhr weiterhin genau geht. Deine obige Berechnung ist genau das, was ich meine. Bei meinem Rechner müsste zwei- bis dreimal pro Minute das Intervall auf 999 gesetzt werden. Unabhängig von den Messerergebnissen: Wenn Du das Intervall immer neu berechnest, kommt bei der Berechnung halt (fast) immer 1000 heraus, dann wird eben das Intervall (fast) immer auf 1000 gesetzt, macht nix. Sollte aber mal (irgendwann im Laufe des Jahres) aus welchem Grund auch immer, die Uhr etwas nachgehen, dann korrigiert sie sich eben halt dann bei der Berechnung des Intervalls zur nächsten Sekunde. Die Schaltsekunde von vor Kurzem hätte sie so auch automatisch korrigieren können. Auch eine beliebige Umstellung der Systemuhr (um Sekundenbruchteile) würde sie so automatisch korrigieren. Sagen wir mal so: Wenn Du hier in Deinen Quelltext noch meine Routine von oben einbaust
Delphi-Quellcode:
bin ich schon zufrieden.
QueryPerformanceCounter(endTime);
timer2.Interval := CalcTimerInterval(iOneSecond); timer2.Enabled:=true; ShowMessage('Die Routine benötigte etwa ' + IntToStr((endTime - startTime) * 1000 div freq) + ' ms'); Um zu prüfen, ob dies auch wirklich geht, setze die Aktuallisierungszeit mal auf die volle Minute und schau dann, ob die Zeitangabe immer HH:MM:00,000 (+/- 1 MS) ist. Als Chromleiste: Baue, wenn Du mit dem bisherigen klargekommen bist und das zu Deiner Zufriedenheit funktioniert, mal einen Nachfahren von TTimer, der, beim Setzen von Enabled := True, automatisch das Intervall auf die nötige Anzahl von Millisekunden bis zur nächsten vollen Sekunde setzt. Ein von mir gebauter TTimer-Nachfahre hat u. a. folgende Attribute:
Delphi-Quellcode:
Sie dienen dazu, wenn einer der boolschen Werte gesetzt ist, wird das Timerereignis zu exakt diesem Zeitpunkt ausgelöst. Es kann (neben Enabled) immer nur einer der Werte auf True stehen. Die Änderung eines der Werte setzt die anderen automatisch auf False. Das Setzen von Enabled auf True berechnet automatisch für das Intervall die benötigte Anzahl von Millisekunden bis zum Eintreten dieses Zeitpunktes, ist keiner der boolschen Werte gesetzt, so wird das Intervall unverändert belassen, es bleibt also die Funktionälität des Vorfahrens TTimer erhalten.
// Zu jeder vollen Sekunde (HH:MM:00,000, HH:MM:01,000, HH:MM:02,000, ...)
property OneSecond : Boolean read GetOneSecond Write SetOneSecond default False; // Alle fünf Sekunden (HH:MM:00,000, HH:MM:05,000, HH:MM:10,000, ...) property FiveSeconds : Boolean read GetFiveSeconds Write SetFiveSeconds default False; // Alle fünfzehn Sekunden (HH:MM:00,000, HH:MM:15,000, HH:MM:30,000, ...) property FifteenSeconds : Boolean read GetFifteenSeconds Write SetFifteenSeconds default False; // Jede volle Minute (HH:01:00,000, HH:02:00,00, HH:03:00,000 ...) property OneMinute : Boolean read GetOneMinute Write SetOneMinute default False; // Jede vollen fünf Minuten (HH:00:00,000, HH:05:00,000, HH:10:00,000, ...) property FiveMinutes : Boolean read GetFiveMinutes Write SetFiveMinutes default False; // Jede vollen fünfzehn Minuten (HH:00:00,000, HH:15:00,000, HH:30:00,000, ...) property FifteenMinutes : Boolean read GetFifteenMinutes Write SetFifteenMinutes default False; // Jede volle Stunde (01:00:00,000, 02:00:00,000, 03:00:00,000 ...) property OneHour : Boolean read GetOneHour Write SetOneHour default False; // Um Mitternacht (00:00:00,000) property Midnight : Boolean read GetMidnight Write SetMidnight default False; property Enabled : Boolean read GetEnabled Write SetEnabled default False; property Interval : Cardinal read GetInterval Write SetInterval default 1000; property OnTimer : TNotifyEvent read fOnTimer Write SetOnTimer; |
![]() |
Registriert seit: 1. Mai 2016 Ort: Berlin 419 Beiträge Delphi 10.2 Tokyo Professional |
#4
ich hab Deiner Empfehlung folgend beiliegendes geschrieben. Bin aber selbst davon nicht so richtig überzeugt, zumal sich der constructor create nicht aufrufen läßt und auch sonst ist das wohl so la la...
Ist es zuminstest etwa in die richtige Richtung? Was sollte ich also mit der abgeleiteten class tun? (hoffentlich keine zu blöde Frage)
Norbert
|
![]() |
Registriert seit: 18. Nov 2015 Ort: Kehl 678 Beiträge Delphi 11 Alexandria |
#5
Ok dann gebe ich auch noch meinen Senf dazu.......
Ich schreibe jetzt hier nur mal was mir beim überfliegen so aufgefallen ist ![]()
Delphi-Quellcode:
So kannst Du jederzeit die Form mit UpdateVisual(now) updaten;
procedure TForm1.Timer2Timer(Sender: TObject); // Messung Intervall
begin Timer2.Enabled := false; UpdateVisualData(now); Timer2.Interval := CalcTimerInterval(iOneSecond); Timer2.Enabled := true; end; procedure TForm1.UpdateVisualData(const Present: TDateTime); // Update Form var Present: TDateTime; Year, Month, Day, Hour, Min, Sec, MSec: Word; Zeit: string; begin SysUtils.DecodeDate(Present, Year, Month, Day); Label1.Caption := 'Der heutige Tag ist der ' + DezInRoem(IntToStr(Day)) + ' des ' + DezInRoem(IntToStr(Month)) + '. Monates ' + ' des Jahres ' + DezInRoem(IntToStr(Year)); SysUtils.DecodeTime(Present, Hour, Min, Sec, MSec); Label2.Caption := DezInRoem(IntToStr(Hour)) + ' Stunden, ' + DezInRoem(IntToStr(Min)) + ' Minuten und ' + DezInRoem(IntToStr(Sec)) + ' Sekunden und ' + DezInRoem(IntToStr(MSec)) + ' Milisekunden'; Label4.Caption := DezInRoem(IntToStr(Hour)); Label5.Caption := DezInRoem(IntToStr(Min)); Label6.Caption := DezInRoem(IntToStr(Sec)); Label7.Caption := DezInRoem(IntToStr(MSec)); Zeit := timeToStr(Time); Panel1.Caption := Zeit; StatusBar1.Panels[0].Text := timeToStr(Time); StatusBar1.Panels[1].Text := FormatDateTime('"Heute ist "dddd," der "d.mmmm yyyy"', Date); DecodeTime(Time, Hour, Min, Sec, MSec); TrackBar1.Position := Sec; end; Wie z.B in deinem Button2Click
Delphi-Quellcode:
Ach ja schau Dir auch noch die System.DateUtils; an. Da sind einige interessante Routinen rund um Time/Date drin
procedure TForm1.Button2Click(Sender: TObject);
var freq: Int64; startTime: Int64; endTime: Int64; begin Timer2.Enabled := false; if QueryPerformanceFrequency(freq) and QueryPerformanceCounter(startTime) then begin // Befehlesfolge deren Zeitdauer bestimmt werden soll UpdateVisualData(now); QueryPerformanceCounter(endTime); ShowMessage('Die Routine benötigte etwa ' + IntToStr((endTime - startTime) * 1000 div freq) + ' ms'); end else begin // Hier sollte eigentlich untersucht werden was nicht gegangen ist getLastError oder so ShowMessage('OOPS'); end; Timer2.Enabled := true; end;
Fritz Westermann
|
![]() |
nahpets
(Gast)
n/a Beiträge |
#6
Hab' mir den Quelltext mal angeschaut.
Wenn man einen Timer auf Enabled setzt, so wird der in Intervall befindliche Zeitraum genutzt. Wird das Intervall erst nach Enabled := True; gesetzt, so hat es keine Auswirkung mehr, bzw. erst nach dem nächsten Enabled := False; ... Enabled := True; Hab' einfach mal ein bisserl überarbeitet:
Delphi-Quellcode:
Bei der Uhr vom Düsseldorfer Fernmeldeturm meinte ich übrigens dieses hier:
unit Unit1;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ComCtrls, ExtCtrls, Math, {$IFDEF VER150} // Delphi 7 StdCtrls, Buttons, jpeg; {$ELSE} Vcl.StdCtrls, Vcl.Buttons, Vcl.Imaging.jpeg; {$ENDIF} type TTimerNW = class(TTimer) private fOneSecond : Boolean; fMidnight : Boolean; function CalcTimerInterval(iTimerInterval : Integer) : Integer; function GetEnabled:boolean; function GetInterval: cardinal; procedure init; procedure SetEnabled(e: boolean); procedure SetInterval(i: cardinal); procedure SetMidNight(AValue : Boolean); procedure SetOneSecond(AValue : Boolean); public constructor Create(AOwner: TComponent); override; destructor Destroy; override; published property Enabled : Boolean read GetEnabled write SetEnabled default False; property Interval : Cardinal read GetInterval write SetInterval default 1000; property OneSecond : Boolean read fOneSecond write SetOneSecond; property MidNight : Boolean read fMidNight write SetMidNight; end; type TForm1 = class(TForm) BitBtnClose: TBitBtn; Button1: TButton; Button2: TButton; Button3: TButton; Image1: TImage; Label1: TLabel; Label2: TLabel; Label3: TLabel; Label4: TLabel; Label5: TLabel; Label6: TLabel; Label7: TLabel; Panel1: TPanel; StatusBar1: TStatusBar; TrackBar1: TTrackBar; procedure BitBtnCloseClick(Sender: TObject); procedure Sekundenanzeige(Sender: TObject); procedure Datumsanzeige(Sender: TObject); procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private { Private-Deklarationen } fTimer : TTimerNW; ftmDatum : TTimerNW; procedure Ausgabe; public { Public-Deklarationen } end; const iOneSecond : Integer = 1000; // eine Sekunde in Millisekunden iFiveSeconds : Integer = 5000; // fünf Sekunden in Millisekunden iFifteenSeconds : Integer = 15000; // fünfzehn Sekunden in Millisekunden iOneMinute : Integer = 60000; // eine Minute in Millisekunden iFiveMinutes : Integer = 300000; // Fünf Minuten in Millisekunden iFifteenMinutes : Integer = 900000; // Fünfzehn Minuten in Millisekunden iOneHour : Integer = 3600000; // Eine Stunde in Millisekunden iOneDay : Integer = 86400000; // Ein Tag in Millisekunden csHeute = 'Der heutige Tag ist der %s des %s. Monates des Jahres %s.'; csUhrzeit = '%s Stunden, %s Minuten, %s Sekunden und %s Millisekunden'; var Form1: TForm1; implementation {$R *.dfm} constructor TTimerNW.create; begin inherited Create(AOwner); fOneSecond := False; fMidnight := False; init; end; destructor TTimerNW.Destroy; begin inherited Destroy; end; procedure TTimerNW.init; begin inherited Interval := 1000; inherited Enabled := True; end; procedure TTimerNw.SetEnabled(e: Boolean); begin if fOneSecond then Interval := CalcTimerInterval(iOneSecond) else if fMidNight then Interval := CalcTimerInterval(iOneDay); inherited Enabled := e; end; procedure TTimerNW.SetInterval(i: Cardinal); begin if i = 0 then i := 1000; inherited Interval := i; end; function TTimerNW.GetInterval; begin inherited; Result := inherited Interval; end; function TTimerNW.GetEnabled; begin Result := inherited Enabled; end; function TTimerNW.CalcTimerInterval(iTimerInterval : Integer) : Integer; Var dNow : Double; begin // Interval setzen // Tagesdatum und Uhrzeit holen dNow := Now; // Den Tagesanteil holen (= Nachkommastellen). dNow := dNow - Trunc(dNow); // Rest bis Mitternacht holen. dNow := 1 - dNow; // Nachkommastellen mal Millisekunden pro Tag Result := Trunc(dNow * iOneDay); // wir benötigen den Rest bis zum angegeben Interval, damit der Timer // zur nächsten Minute, Stunde, 0 Uhr ... aktive wird. Result := (Result mod Max(iTimerInterval,1)); end; procedure TTimerNW.SetOneSecond(AValue : Boolean); begin fOneSecond := AValue; if AValue then begin fMidNight := false; Interval := CalcTimerInterval(iOneSecond); end; end; procedure TTimerNW.SetMidNight(AValue : Boolean); begin fMidNight := AValue; if AValue then begin fOneSecond := false; Interval := CalcTimerInterval(iOneDay); end; end; function DezInRoem(n:Integer):string; function teil(const groessenordnung1,groessenordnung2:integer; var rest:integer; const zeichen1,zeichen2:char):string; begin result:=''; while rest>=groessenordnung1 do begin dec(rest,groessenordnung1); //rest:=rest-groessenordnung; result:=result+zeichen1; //z.B. +'M' end; if rest>=groessenordnung2 then begin dec(rest,groessenordnung2); result:=result+zeichen2+zeichen1; //z.B. +'CM' End; end; begin result := ''; //in Delphi automatisch result := result + teil(1000,900,n,'M','C'); result := result + teil( 500,400,n,'D','C'); result := result + teil( 100, 90,n,'C','X'); result := result + teil( 50, 40,n,'L','X'); result := result + teil( 10, 9,n,'X','I'); result := result + teil( 5, 4,n,'V','I'); result := result + teil( 1, 1,n,'I','I'); end; procedure TForm1.BitBtnCloseClick(Sender: TObject); begin close; end; procedure TForm1.Button1Click(Sender: TObject); var startTime: Cardinal; begin startTime := GetTickCount; //Befehlesfolge deren Zeitdauer bestimmt werden soll Ausgabe; // ShowMessage('Die Routine benötigte etwa ' + (IntToStr(GetTickCount - startTime)) + ' ms'); fTimer.Enabled := true; // showMessage(floattostr(timer2.Interval)); end; procedure TForm1.Button2Click(Sender: TObject); var freq: Int64; startTime: Int64; endTime: Int64; begin fTimer.Enabled := false; QueryPerformanceFrequency(freq); QueryPerformanceCounter(startTime); //Befehlesfolge deren Zeitdauer bestimmt werden soll Ausgabe; QueryPerformanceCounter(endTime); fTimer.Enabled := true; // ShowMessage('Die Routine benötigte etwa ' + IntToStr((endTime - startTime) * 1000 div freq) + ' ms'); end; procedure TForm1.Button3Click(Sender: TObject); begin // Damit der Timer zur nächsten vollen Sekunde ausgelöst wird: fTimer.Interval := fTimer.CalcTimerInterval(iOneSecond); //showMessage(inttostr(CalcTimerInterval(iOneSecond))); // showMessage(inttostr(Timer2.Interval)); // Zur nächsten vollen Viertelstunde, um den Glockenschlag für die Viertelstunde auszulösen: fTimer.Interval := fTimer.CalcTimerInterval(iFifteenMinutes); // Oder um Mitternacht, z. B. für den Datumswechsel: fTimer.Interval := fTimer.CalcTimerInterval(iOneDay); end; procedure TForm1.Sekundenanzeige(Sender: TObject); //Messung Intervall var freq : Int64; startTime: Int64; endTime : Int64; Present : TDateTime; Hour, Min, Sec, MSec: Word; begin fTimer.Enabled := false; QueryPerformanceFrequency(freq); QueryPerformanceCounter(startTime); Ausgabe; Present := Now; Panel1.Caption := timeToStr(Present); StatusBar1.Panels[0].Text := TimeToStr(Present); SysUtils.DecodeTime(Present, Hour, Min, Sec, MSec); Trackbar1.Position := Sec; QueryPerformanceCounter(endTime); fTimer.Enabled := true; // ShowMessage('Die Routine benötigte etwa ' + IntToStr((endTime - startTime) * 1000 div freq) + ' ms'); end; procedure TForm1.Datumsanzeige(Sender: TObject); var Present : TDateTime; begin ftmdatum.Enabled := false; Present := Now; Panel1.Caption := timeToStr(Present); StatusBar1.Panels[1].Text := FormatDateTime('"Heute ist "dddd," der "d.mmmm yyyy"',Present); ftmDatum.Enabled := true; end; procedure TForm1.FormCreate(Sender: TObject); begin fTimer := TTimerNW.Create(Self); fTimer.OnTimer := Sekundenanzeige; fTimer.OneSecond := True; Sekundenanzeige(Sender); ftmDatum := TTimerNW.Create(Self); ftmDatum.MidNight := True; Datumsanzeige(Sender); end; procedure TForm1.FormDestroy(Sender: TObject); begin ftmDatum.Free; fTimer.Free; end; procedure TForm1.Ausgabe; var Present: TDateTime; Year, Month, Day, Hour, Min, Sec, MSec: Word; begin Present := Now; SysUtils.DecodeDate(Present, Year, Month, Day); SysUtils.DecodeTime(Present, Hour, Min, Sec, MSec); Label1.Caption := Format(csHeute,[Dezinroem(Day), Dezinroem(Month), DezinRoem(Year)]); Label2.Caption := Format(csUhrzeit,[DezInRoem(Hour),DezInRoem(Min), DezinRoem(Sec), DezinRoem(MSec)]); Label4.Caption := DezInRoem(Hour); Label5.Caption := DezInRoem(Min); Label6.Caption := DezInRoem(Sec); Label7.Caption := DezInRoem(mSec); end; end. ![]() ![]() ![]() |
![]() |
Ansicht |
![]() |
![]() |
![]() |
ForumregelnEs ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus. Trackbacks are an
Pingbacks are an
Refbacks are aus
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
![]() |
![]() |