19. april 2001 - 11:47Der er
8 kommentarer og 1 løsning
Tids-forbrug
Findes der en component/kommando/procedure der kontinuerligt viser anvendt tid, á la uret på Windows bundlinie - men som starter fra 0 timer 0 min - placeret på Form1 canvas i et SDI program, og uanset det videre program forløb?
Ikke direkte men du kan når dit program starter op lave kalde funktionen GetTickCount, den returnere så hvor mange milisekunder der er gået siden at computeren blev startet. Og så laver du en onIdle eventhandler for din applikation hvor du blot hele tiden træker det oprindelige TickCount fra den nuværende og så regner det om til Timer og minutter hvis det er den måde du vil have det på.
function Tform1.Duration(ms: integer):string; //konverterer millisekunder til sekunder, minutter, timer osv. var temp, temp2: string; begin Fday:=0; Fhour:=0; Fmin:=0; Fsec:=0; FTotal:=0; temp:=\'\'; FDay := ms div cDay; Ftotal:=ms mod cday; FHour := Ftotal div cHour; Ftotal:=Ftotal mod chour; FMin := Ftotal div cMin; Ftotal:=Ftotal mod cmin; FSec := Ftotal div cSec; Ftotal:=Ftotal mod cSec; Fdec:=Ftotal div cDec; temp2:=inttostr(Fmin); if length(temp2)=1 then temp2:=temp2; temp := temp + Temp2+\':\'; temp2:=inttostr(FSec); if length(temp2)=1 then temp2:=\'0\'+temp2; temp := temp + temp2+\':\'; temp2:=inttostr(FDec); if length(temp2)=1 then temp2:=\'0\'+temp2; result:=temp+temp2; end;
(OnformCreate): oldtid := Gettickcount
(OnTimer) label1.caption:=duration(gettickcount-oldtime); //Indsætter den konverterede tid der er gået siden dit program startede op ind i en label.
Det virker på spørgsmålet som om der bare er brug for en ca. tid - ihvertflad nævnes kun timer og minutter. I såfald er GetTickCount nok ikke lige hvad der søges. En anden ting er, at den værdi som GetTickCount anvender internt i Windows er placeret som en 32 bit værdi. Dette betyder at den på et eller andet tidspunkt vil løbe over (efter 49.7 dage), hvilket man i nogen sammenhænge skal tage hensyn til, fx. i applicationer til servere, der ofte kan stå tændte i sådanne tidsrum.
Delphi har er udemærket system til tidsstyring i TDateTime typen. Nedenstående eksempel viser således hvorledes en label på en form opdateres med aktuel tid. Application.onIdle benyttes til opdateringen, så der bruges så og sige ingen systemresourcer.
Bemærk i øvrigt at rutinen TimeTostr benytter den global variable LongTimeFormat til specifikation af hvorledes tiden skal angives. Denne variabel sættes, når dit program startes, af Delphi Runtime til hvorledes brugeres har specificeret det i control panelet (reginal settings). Du lader dermed brugeren selv bestemme hvorledes tiden skal skrives - men kan se\'følig overskrive, fx. med:
LongTimeFormat := \'hh:nn\'; // Viser kun timer og minutter.
procedure TForm1.IdleHandler(Sender: TObject; var Done: Boolean); Var NowStr : String; begin NowStr := TimeTostr(Now - FStartTime); If NowStr<>Label1.Caption Then Label1.Caption := NowStr; end;
Har du brug for også at se dage programmet har kørt, så kan du ændre Nowstr tildelings linien ovenfor til fx.:
Du har ret - det er dit forslag jeg kan bruge, men proceduren \'onIdle\' giver problemer:
1: Kan det være rigtigt at den skal angives i \'private\' som du skriver? Der fejlmeldes: unsatisfied forward or external declaration\'.
2: Hvordan oprettes samme procedure under \'implemation\' ? Der fejlmeldes: \'undeclared identifier\'.
Det er vel mit begrænsede kendskab til Delphi som giver mig problemer men hvis du vil angive - \'klippet ud i pap\' hvordan problemet løses, forhøjer jeg med 30 point.
Du mener vel proceduren \'IdleHandler\' og ikke \'onIdle\'? (onIdle er en event pointer defineret i TApplication classen)
1: Ja, det er smartest at placere den under Private. Der burde ikke umiddelbart være andre class\'er/programdele i dit program, der har brug for at kalde IdleHandler i din form. MEN hvis du vil kalde den et andet sted fra, så er du velkommen til at placere den under fx. Public delen af din class - herved bliver den synlig for andre class\'er.
Du skriver: \"Der fejlmeldes: unsatisfied forward or external declaration\'\"
Prøv lige at checkke din kode igen. Det virker som om du har skrevet forkert. Det virker fint i den here ende.
2: Med spørgsmålet \"Hvordan oprettes samme procedure under \'implemation\' ?\", går jeg ud fra at du mener som en standard procedure - i modsætning til en metode defineret under en class.
Nej, dette kan ikke lade sig gøre. Grunden er, at TApplication.onIdle er defineret som en pointer til en object method.
Det du i stedet kan gøre er følgende:
1: Flyt IdleHandler metoden ud af TForm1 class\'en som en standard procedure, der placeres under Implementation linien. Fjern de parametre der er på proceduren - de benyttes ikke.
2: Fjern følgende linie fra din forms create del: Application.OnIdle := IdleHandler;
2: Alle fields fra TForm1, fx. FStartTime, der benyttes i IdleHandler skal flyttes til class\'ens Public eller Protected del, således at de kan ses fra IdleHandler. Desuden skal alle referencer til disse fields \'qualifies\', dvs. i stedet for at skrive:
3: Placer en timer, fra Delphis System palette, på din form. Sæt timerens Interval property til noget passende. Jo lavere værdi, jo oftere kaldes dens onTimer method og jo mere belastes CPU\'en. Hvis du fx. ønsker en opdatering hvert sekund, så sæt propertien til 1000 (mSek\'s). Hvis en opdatering hvert minut er fint, så sæt værdien til 60000.
4: Dobbelt click på Timeren (For at oprette en onTimer method). skriv følgende linie i denne methods body:
type TForm1 = class(TForm) Label1: TLabel; Timer1: TTimer; procedure FormCreate(Sender: TObject); procedure Timer1Timer(Sender: TObject); private { Private declarations } Protected FStartTime : TDateTime; public { Public declarations } end;
var Form1: TForm1;
implementation
procedure IdleHandler; Var NowStr : String; begin NowStr := TimeTostr(Now - Form1.FStartTime); If NowStr<>Form1.Label1.Caption Then Form1.Label1.Caption := NowStr; end;
Ok, spørgsmålet er afsluttet, så du har nok fundet ud af det.
Bemærk, at jeg til hver en tid vil vælge den første metode. Det er ikke smart at anvende timere hvis det kan undgås. De er en begrænset resource under Windows.
Jov, du har ret... der var en \'lus\' i koden, og nu virker den 1.ste version - label-componenten viser tiden ved start med 00.00. Imidlertid skifter tiden ikke før tastatur eller mus aktiveres - altså ikke kontinuerlig display ved stilstand (idle), men omvendt (når aktiv) ?
Hvorfor...
Tak iøvrigt for dine hurtige svar og jeg håber du orker at fix\'e det sidste problem...
Jeg har også bemærket, at Idle eventen kun kaldes ca. hvert tiende sekund, hvis mus/tastatur ikke påvirkes. Egentligt lidt underligt, idet der netop i denne situation burde være masser af Idle time.
Hvis mere nøjagtig tidsangivelse er påkrævet, så må du anvende en Timer til opdateringen.
Peter
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.