Programowanie w języku Delphi » Gotowce

Odliczanie

Ostatnio dostałem list z prośbą napisania programu, który odliczałby czas od
podanej wartości do zera. Przy czym czas musiałbyć zapisany w postaci:
HH:MM:SS. Czyli program wyglądałby jak stoper tyle, że od podanej wartości
czasowej do 0.

Co nam będzie potrzebne? Przede wszystkim komponent Timer. Umieść go na
formularzu i zmień
jego wartość Enabled na False. Wszystko co nam będzie potrzebne to komponent
Timer oraz
polecenia EncodeTime i DecodeTime. Te polecenia służą do rozdzielania
zmiennej czasowej
typu TTime na oddzielne wartości (godziny, minuty, sekundy), a następnie na
podstawie podanych wartości połączenie ich w zmienną typu TTime.

Na formularzu umieść dodatkowo komponent MaskEdit, który będzie dbał o
poprawność
wprowadzanych danych. Czyli użytkownik nie będzie mógł wpisać żadnych liter,
a tylko
cyfry. Ustaw maskę tego komponentu na LongTime.

Dekodowanie czasu na poszczególne "człony" wygląda tak:


BeforeTime := StrToTime(meTime.Text); // pobierz tekst z kontrolki iprzeksztalc go na zmienna TTime
DecodeTime(BeforeTime, wHour, wMin, wSec, wMSec); // rozłącz czas nagodziny, minuty i sekundy




Natomiast kodowanie wartości na zmienną czasową następująco:


{ tak zmodyfikowane wartosci przeksztalc do postaci zmiennej typu TTime iwyswietl
    na kontrolce TMaskEdit }
  AfterTime := EncodeTime(wHour, wMin, wSec, wMSec);
  meTime.Text := TimeToStr(AfterTime);




Zdarzenie OnTimer komponentu Timer występować będzie co 1000 milisekund,
czyli co jedną sekundę. Następować w niej będzie
zmniejszanie wartości wSec (która to oznacza ilość sekund) i ew.
zmniejszenie pozostałych wartości, czyli wMin oraz wHour.
Przy tym trzeba będzie zastosować trochę warunków if aby wszystko było tak
jak trzeba.

Cała procedura OnTimer wygląda tak:

procedure TMainForm.TimerTimer(Sender: TObject);
var
  BeforeTime, AfterTime : TTime;
  wHour, wMin, wSec, wMSec : Word;
begin
  BeforeTime := StrToTime(meTime.Text); // pobierz tekst z kontrolki i przeksztalc go na zmienna TTime
  DecodeTime(BeforeTime, wHour, wMin, wSec, wMSec); // rozłącz czas na godziny, minuty i sekundy
 
  Dec(wSec); // zmniejsz liczbe sekund
  { tutaj nastepuje sprawdzenie, czy odliczanie sie zakonczylo. Jezeli liczba godzin
  minut i sek rowna sie 0 to nastepuje wylaczenie timera i uruchomienie procedury "Run"
  }
  if ((wSec = 0) and (wMin = 0) and (wHour = 0)) then
  begin
    Timer.Enabled := False; // wylacz timer
    btnGo.Caption := 'Odliczaj...'; // zmień wartość Caption
    Run; // wywolaj procedure
    Exit;
  end;
 
  if wSec = 0 then  // sprawdz, czy liczba sekund nie rowna sie przypadkiem0
  begin
    wSec := 59; // w takim wypadku zmien te wartosc na 59
 
  { jezeli liczba godzin oraz liczba minut rowna sie 0 to zmniejsz liczegodzin,
    a zmiennej wMin przypisz wartosc 60 }
    if ((wHour > 0) and (wMin = 0)) then begin dec(wHour); wMin := 60;end;
  { jezeli liczba minut jest wieksza od 0 to zmniejsz te wartosc o jeden }
    if wMin > 0 then dec(wMin);
  end;
 
  { tak zmodyfikowane wartosci przeksztalc do postaci zmiennej typu TTime iwyswietl
    na kontrolce TMaskEdit }
  AfterTime := EncodeTime(wHour, wMin, wSec, wMSec);
  meTime.Text := TimeToStr(AfterTime);
end;



Czyli następuje tutaj sprawdzenie czy przypadkiem odliczanie się nie
zakończyło. Później w przypadku, gdy wartość wSec wyniesie 0 trzeba będzie
sprawdzić parę warunków. Bowiem liczba minut może wynieść 0 - wtedy trzeba
będzie zmniejszyć o jeden
wartość godzin. Także w przypadku, gdy ilość sekund wyniesie 0 to trzeba
będzie ponownie przypisać tej wartości liczbę 59,
a później zmniejszyć o jeden liczbę minut. Itd., itp.

Cały kod źródłowy programu wygląda tak:


(****************************************************************)
(*                                                              *)
(*            Copyright (c) 2002 by Adam Boduch                 *)
(*                http://4programmers.net                       *)
(*                 [email protected]                        *)
(*                                                              *)
(****************************************************************)
 
unit MainFrm;
 
interface
 
uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls, Mask;
 
type
  TMainForm = class(TForm)
    meTime: TMaskEdit;
    Timer: TTimer;
    btnGo: TButton;
    procedure btnGoClick(Sender: TObject);
    procedure TimerTimer(Sender: TObject);
  private
    procedure Run;
  end;
 
var
  MainForm: TMainForm;
 
implementation
 
{$R *.dfm}
 
procedure TMainForm.Run;
begin
{ wyświetl okienko informacyjne w przypadku skończenia odliczania }
  ShowMessage('Skończone');
end;
 
procedure TMainForm.btnGoClick(Sender: TObject);
begin
{
   tutaj nastepuje ew. sprawdzenie, czy Timer jest uruchomiony - jezelitak
   to jest mozliwosc zatrzymania jego - w przeciwnym wypadku - nastepujeuruchomienie
}
  if not Timer.Enabled then
  begin
    Timer.Enabled := True;
    btnGo.Caption := 'Zatrzymaj...';
  end else
  begin
    Timer.Enabled := False;
    btnGo.Caption := 'Odliczaj...';
  end;
end;
 
procedure TMainForm.TimerTimer(Sender: TObject);
var
  BeforeTime, AfterTime : TTime;
  wHour, wMin, wSec, wMSec : Word;
begin
  BeforeTime := StrToTime(meTime.Text); // pobierz tekst z kontrolki iprzeksztalc go na zmienna TTime
  DecodeTime(BeforeTime, wHour, wMin, wSec, wMSec); // rozłącz czas nagodziny, minuty i sekundy
 
  Dec(wSec); // zmniejsz liczbe sekund
  { tutaj nastepuje sprawdzenie, czy odliczanie sie zakonczylo. Jezeliliczba godzin
  minut i sek rowna sie 0 to nastepuje wylaczenie timera i uruchomienieprocedury "Run"
  }
  if ((wSec = 0) and (wMin = 0) and (wHour = 0)) then
  begin
    Timer.Enabled := False; // wylacz timer
    btnGo.Caption := 'Odliczaj...'; // zmień wartość Caption
    Run; // wywolaj procedure
    Exit;
  end;
 
  if wSec = 0 then  // sprawdz, czy liczba sekund nie rowna sie przypadkiem0
  begin
    wSec := 59; // w takim wypadku zmien te wartosc na 59
 
  { jezeli liczba godzin oraz liczba minut rowna sie 0 to zmniejsz liczegodzin,
    a zmiennej wMin przypisz wartosc 60 }
    if ((wHour > 0) and (wMin = 0)) then begin dec(wHour); wMin := 60;end;
  { jezeli liczba minut jest wieksza od 0 to zmniejsz te wartosc o jeden }
    if wMin > 0 then dec(wMin);
  end;
 
  { tak zmodyfikowane wartosci przeksztalc do postaci zmiennej typu TTime iwyswietl
    na kontrolce TMaskEdit }
  AfterTime := EncodeTime(wHour, wMin, wSec, wMSec);
  meTime.Text := TimeToStr(AfterTime);
end;
 
end.



Cały kod programu możesz ściągnąć tutaj:

4 komentarze

_0L3k_ 2008-05-06 12:34

W tym programie coś brakuje bo jak się ustawi pełną godzinę lub minutę to wyrzuca błąd. Nie dzieje się to tylko jak się doda przynajmniej jedną sekundę.

Wolverine 2007-03-19 11:34

Nigdy nie ufaj, ze timer wywola ci metode rowno po sekundzie, co jesli w tym momecie twoj program nie bedzie mial dostepu do procesora (co jest wysoce prawdopodobne) i co jesli to sie powtorzy kilka tysiecy razy? Do takich rzeczy uzywa sie RTC (choc zauwazylem, ze w moim laptopie zegarek potrafi sie presunac az o 10 sek w ciagu dnia! ale to inna historia ;)

BcbMan 2005-11-25 14:09

Nie jestem pewien, czy dobrze zrozumialem problem, ale wydaje mi sie ze ponizszy kod bedzie robil cos podobnego (opuszczam graficzna otoczke, zeby nie dublowac kodu).

program KoncoweOdliczanie;
 
{$APPTYPE CONSOLE}
 
uses
  SysUtils;
 
var
  tekst : String;
  czas_kon, czas : TDateTime;
 
begin
  Writeln('Program stosuje koncowe odliczanie (max. 23h59m59s).');
  Write('Podaj czas odliczania w formacie h:m:s : ');
  Readln(tekst);
 
  czas := StrToTime(tekst);   czas_kon := Now + czas;
 
  Writeln;
  while Now<czas_kon do
   begin
     Write(#13, TimeToStr(czas_kon-Now));
     Sleep(250); // to nie jest niezbedne
   end;
  Writeln(#13#10#13#10'Odliczanie zakonczone. Nacisnij [ENTER], aby zakonczyc program...');
  Readln;
end.


Pozdrawiam, BcbMan.

akarame 2004-02-18 17:07

Link nie dziala. Blad 404???