Thema: Analoguhr

Einzelnen Beitrag anzeigen

Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#23

Re: Analoguhr

  Alt 28. Apr 2004, 05:16
Ich finde das irgendwie nicht so schön deinen Spaghetti-Code da. Du hast da ja im Prinzip immer wiederkehrenden Code zum Zeichnen der Zeiger nur mit anderen Winkeln und Längen. Schreib eine Prozedur dafür, der du die entsprechenden Werte als Parameter übergibst. So hast du keinen reduntanten Code. Siehe dazu meine Prozeduren ClearHands und PaintHands. Die hätte man auch noch zusammenfassen können, in dem man eine boolsche Variable mitgibt, die bestimmt, ob gezeichnet oder gelöscht werden soll.
Und durch das Zeichen auf das Bitmap im Speicher und das Kopieren des Bitmaps in OnPaint der Paintbox auf den Canvas der Paintbox, sind die Zeiger auch sofort wieder da, wenn das Fenster überdeckt wird und nicht erst nach einer Sekunde wieder, wenn bei dir der Timer ausgelöst wird.

Ich würde es so lösen:
Delphi-Quellcode:
type
  TForm1 = class(TForm)
    Timer1: TTimer;
    PaintBox1: TPaintBox;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure PaintBox1Paint(Sender: TObject);
    procedure FormResize(Sender: TObject);
  private
    { Private declarations }
    OldHrs, OldMins, OldSecs: Integer;
    BackBitmap: TBitmap; // Bitmap im Speicher zum Zeichnen
    procedure ClearHands(Start: TPoint; Angle, Len: Integer);
    procedure PaintHands(start: TPoint; Angle, Len: Integer);
  public
    { Public declarations }
  end;

const
  RADIUS = 100;

var
  Form1 : TForm1;

implementation

{$R *.dfm}

uses
  Math;

{------------------------------------------------------------------------------}
{  Zeiger löschen                                                              }
{------------------------------------------------------------------------------}
procedure TForm1.ClearHands(Start: TPoint; Angle, Len: Integer);
var
  EndPos : TPoint;
begin
  // Anfangspunkt in die Mitte des Bitmaps setzten
  BackBitmap.Canvas.Pen.Color := clWhite;
  // Zeiger neu zeichnen
  EndPos.X := Trunc(sin(DegToRad(Angle)) * (RADIUS+Len));
  EndPos.Y := Trunc(cos(DegToRad(Angle)) * -(RADIUS+Len));
  BackBitmap.Canvas.MoveTo(Start.X, Start.Y);
  BackBitmap.Canvas.LineTo(Start.X+EndPos.X, Start.Y+EndPos.Y);
end;

{------------------------------------------------------------------------------}
{  Zeiger zeichnen                                                             }
{------------------------------------------------------------------------------}
procedure TForm1.PaintHands(Start: TPoint; Angle, Len: Integer);
var
  EndPos : TPoint;
begin
  // Anfangspunkt in die Mitte des Bitmaps setzten
  BackBitmap.Canvas.Pen.Color := clBlack;
  // Zeiger neu zeichnen
  EndPos.X := Trunc(sin(DegToRad(Angle)) * (RADIUS+Len));
  EndPos.Y := Trunc(cos(DegToRad(Angle)) * -(RADIUS+Len));
  BackBitmap.Canvas.MoveTo(Start.X, Start.Y);
  BackBitmap.Canvas.LineTo(Start.X+EndPos.X, Start.Y+EndPos.Y);
end;

{------------------------------------------------------------------------------}
{  Winkel der Zeiger berechnen                                                 }
{------------------------------------------------------------------------------}
procedure CalcAngels(var hrs, mins, secs, msec: Word);
begin
  DecodeTime(Time, hrs, mins, secs, msec);
  secs := secs * 6;
  mins := mins * 6;
  hrs := hrs * 30;
end;

{------------------------------------------------------------------------------}
{  Form erzeugen                                                               }
{------------------------------------------------------------------------------}
procedure TForm1.FormCreate(Sender: TObject);
begin
  DoubleBuffered := True;
  // Bitmap im Speicher erzeugen
  BackBitmap := TBitmap.Create;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  // Bitmap im Speicher wieder freigeben
  FreeAndNil(BackBitmap);
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
  hrs, mins,
    secs, msec : Word;
  Start : TPoint;
begin
  // Zeit zur Kontrolle mitlaufen lassen
  Caption := TimeToStr(Time);

  // Größe des Bitmaps an die Größe der Paintbox (Align := alClient anpassen
  BackBitmap.Width := Paintbox1.Width;
  BackBitmap.Height := Paintbox1.Height;

  // Startpunkt berechnen (soll immer in der Mitte der Paintbox sein
  Start.X := Paintbox1.Width div 2;
  Start.Y := Paintbox1.Height div 2;

  // Winkel berechnen
  CalcAngels(hrs, mins, secs, msec);

  // Zeiger löschen
  ClearHands(Start, OldSecs, Paintbox1.Height div 2 div 2 - 40);
  // Zeiger zeichnen
  PaintHands(Start, secs, Paintbox1.Height div 2 div 2 - 40);
  // alten Winkel merken
  OldSecs := secs;

  ClearHands(Start, OldMins, Paintbox1.Height div 2 div 3 - 50);
  PaintHands(Start, mins, Paintbox1.Height div 2 div 3 - 50);
  OldMins := mins;

  ClearHands(Start, OldHrs, Paintbox1.Height div 2 div 6 - 60);
  PaintHands(Start, hrs, Paintbox1.Height div 2 div 6 - 60);
  OldHrs := hrs;

  // Neuzeichnen der Paintbox auslösen
  Paintbox1.Repaint;
end;

{------------------------------------------------------------------------------}
{  OnPaint der Paintbox                                                        }
{  Bitmap im Speicher auf die Paintbox kopieren                                }
{------------------------------------------------------------------------------}
procedure TForm1.PaintBox1Paint(Sender: TObject);
begin
  BitBlt(Paintbox1.Canvas.Handle, 0, 0, Paintbox1.Width, Paintbox1.Height,
    BackBitmap.Canvas.Handle, 0, 0, SRCCOPY);
end;

{------------------------------------------------------------------------------}
{  Größe des Bitmap im Speicher auf null setzen                                }
{------------------------------------------------------------------------------}
procedure TForm1.FormResize(Sender: TObject);
begin
  BackBitmap.Width := 0;
  BackBitmap.Height := 0;
end;
Damit wird auch die Uhr immer in der Mitte gezeichnet und die Zeiger passen immer drauf. Im Anhang noch mal das ganze Projekt.
Angehängte Dateien
Dateityp: zip analog_uhr.zip (188,9 KB, 162x aufgerufen)
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat