Registriert seit: 29. Mai 2002
37.621 Beiträge
Delphi 2006 Professional
|
Re: Analoguhr
28. Apr 2004, 06: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.
Michael Ein Teil meines Codes würde euch verunsichern.
|