// Komponente für ein simples Zeigerinstrument.
// Über die Eigenschaft "WertAnzeige" wird geregelt, ob neben der
// Zeigerbewegung auch der entsprechende Wert als Zahl angezeigt wird. Dabei
// legt "Kommastellen" die Anzahl (0..10) der Nachkommastellen fest, und
// "FontFaktor" bestimmt, um welchen Faktor diese Anzeige größer ist als die
// Zahlen der Skala. Mit "Stufe1" und "Stufe2" wird intern der Bereich in 3
// Teilbereiche unterteilt, wobei die Striche der Skala in jedem Teilbereich
// eine andere Farbe haben können. Wenn der Zeiger von einem Teilbereich in den
// anderen übergeht, wird ein Event ausgelöst. Ist die Komponente disabled,
// kann "Value" nicht verändert werden, und es wird kein Zeiger dargestellt.


// Getestet mit D4 unter XP

unit Meter; 
 
interface 
 
uses 
  Windows, SysUtils, Classes, Graphics, Controls, Extctrls, Messages; 
 
type 
  TMeterZahlen = (mAlle, mKeine, mZwei); 
  TZeigerLaenge = (mKurz, mLang, mMittel); 
 
  TMeter = class(TCustomPanel) 
  private 
    FBereich1, FBereich2, FBereich3, FChange: TNotifyEvent; 
    FBereiche, FTeilung, Radius1, Strichgr, Strichkl, FStellen, ib: byte; 
    x1, y1, x2, y2, Wert1, Teilung, Winkel1, Winkel2, Winkel3, FFaktor: single; 
    Wert2, mini, maxi, Radius2, Strich, Bereich, Wert3, fs: integer; 
    FUntergrund, FFarbe1, FFarbe2, FFarbe3, FZeigerfarbe: TColor; 
    FMeterZahlen: TMeterZahlen; 
    s1, s2, FValue: double; 
    FWertAnzeige: boolean; 
    Strichzahl, anz: word; 
    Flang: TZeigerlaenge; 
    s, nk: string; 
    FScala: smallint; 
    sz: TSize; 
  protected 
    procedure MFont(var Msg: TWMSETFONT); message WM_SETFONT; 
    procedure setMeterZahlen(m: TMeterZahlen); 
    procedure setWertAnzeige(b: boolean); 
    procedure setlang(z: TZeigerlaenge); 
    procedure setZeigerfarbe(f: Tcolor); 
    procedure setUntergrund(f: Tcolor); 
    procedure setKommastellen(b: byte); 
    procedure setFaktor(s: single); 
    procedure makeEvent(d: double); 
    procedure setbereiche(b: byte); 
    procedure setFarbe1(f: Tcolor); 
    procedure setFarbe2(f: Tcolor); 
    procedure setFarbe3(f: Tcolor); 
    procedure setTeilung(b: byte); 
    procedure setValue(d: double); 
    procedure setmini(i: integer); 
    procedure setmaxi(i: integer); 
    procedure sets1(d: double); 
    procedure sets2(d: double); 
    procedure setscala(s: smallint); 
    procedure rechnestriche; 
    procedure makeTeilung; 
    procedure makewert; 
    function Punktx(x: Single): Integer; 
    function Punkty(y: Single): Integer; 
  public 
    procedure Paint; override; 
    procedure setEnabled(Value: boolean); override; 
    constructor Create(Owner: TComponent); override; 
  published 
    property Font; 
    property Enabled; 
    property Visible; 
    property BorderStyle; 
    property Stufe1: double read s1 write sets1; 
    property Stufe2: double read s2 write sets2; 
    property Value: double read FValue write setValue; 
    property MinValue: integer read mini write setmini; 
    property MaxValue: integer read maxi write setmaxi; 
    property Farbe1: TColor read FFarbe1 write setFarbe1; 
    property Farbe2: TColor read FFarbe2 write setFarbe2; 
    property Farbe3: TColor read FFarbe3 write setFarbe3; 
    property SkalaStelle: smallint read FScala write setscala; 
    property FontFaktor: single read FFaktor write setFaktor; 
    property Bereiche: byte read FBereiche write setbereiche; 
    property Unterteilung: byte read FTeilung write setTeilung; 
    property ZeigerLaenge: TZeigerlaenge read FLang write setLang; 
    property Kommastellen: byte read FStellen write setKommastellen; 
    property Untergrund: TColor read FUntergrund write setUntergrund; 
    property ZeigerFarbe: TColor read FZeigerfarbe write setZeigerfarbe; 
    property Zahlen: TMeterZahlen read FMeterZahlen write setMeterZahlen; 
    property WertAnzeige: boolean read FWertAnzeige write setWertAnzeige; 
    property OnBereich1: TNotifyEvent read Fbereich1 write FBereich1; 
    property OnBereich2: TNotifyEvent read Fbereich2 write FBereich2; 
    property OnBereich3: TNotifyEvent read Fbereich3 write FBereich3; 
    property OnValueChange: TNotifyEvent read FChange write FChange; 
    property OnMouseDown; 
    property OnMouseMove; 
    property OnDblClick; 
    property OnMouseUp; 
    property OnClick; 
  end; 
 
procedure Register; 
 
implementation 
 
procedure Register; 
begin 
  RegisterComponents('DBR', [TMeter]); 
end; 
 
constructor TMeter.Create(Owner: TComponent); 
begin 
  inherited Create(Owner); 
  Font.Color := clGray; 
  Font.name := 'Arial'; 
  fs := 7; 
  Font.size := fs; 
  bevelouter := bvNone; 
  doublebuffered := true; 
  FStellen := 1; 
  nk := '0'; 
  ib := 0; 
  FFaktor := 1.25; 
  FZeigerfarbe := clFuchsia; 
  FFarbe1 := $33CC33; 
  FFarbe2 := $606060; 
  FFarbe3 := clRed; 
  s1 := 10; 
  s2 := 90; 
  width := 217; 
  height := 135; 
  FUntergrund := clwhite; 
  mini := 0; 
  maxi := 100; 
  Bereich := maxi - mini; 
  FTeilung := 5; 
  FBereiche := 10; ; 
  makeTeilung; 
  rechnestriche; 
  makewert; 
  Strichkl := 5; 
  Strichgr := 8; 
  FMeterZahlen := mAlle; 
  Winkel2 := 1.05; 
  Radius1 := 75; 
  rechnestriche; 
  FLang := mLang; 
  Radius2 := 21; 
  Strich := 62; 
  FScala := 5; 
  FWertAnzeige := true; 
end; 
 
function TMeter.Punktx(x: Single): Integer; 
begin 
  Result := Round(ClientWidth * (x / 100) - 1 + 
    ClientWidth / 2); 
end; 
 
function TMeter.Punkty(y: Single): Integer; 
begin 
  Result := ClientHeight - Round(ClientHeight * 
    ((y - 20) / (FScala + 75))); 
end; 
 
procedure TMeter.setscala(s: smallint); 
begin 
  if s > 70 then s := 70; 
  if FScala = s then exit; 
  FScala := s; 
  repaint; 
end; 
 
procedure TMeter.setlang(z: TZeigerlaenge); 
begin 
  if FLang = z then exit; 
  Flang := z; 
  case z of 
    mLang: Radius2 := 21; 
    mKurz: Radius2 := 11; 
  else Radius2 := 13; 
  end; 
  repaint; 
end; 
 
procedure TMeter.makeTeilung; 
begin 
  Teilung := Bereich / (FBereiche * FTeilung); 
end; 
 
procedure TMeter.setbereiche(b: byte); 
begin 
  if b = FBereiche then exit; 
  FBereiche := b; 
  if FBereiche < 1 then FBereiche := 1; 
  makeTeilung; 
  rechnestriche; 
  repaint; 
end; 
 
procedure TMeter.setTeilung(b: byte); 
begin 
  if b = FTeilung then exit; 
  FTeilung := b; 
  if FTeilung < 1 then FTeilung := 1; 
  makeTeilung; 
  rechnestriche; 
  repaint; 
end; 
 
procedure TMeter.makewert; 
begin 
  Wert2 := round(FValue - mini); 
  if Wert2 > Bereich then Wert2 := Bereich else 
    if Wert2 < 0 then Wert2 := 0; 
end; 
 
procedure TMeter.makeEvent(d: double); 
begin 
  if (d <= s1) and (ib <> 0) then begin 
    ib := 0; 
    if assigned(FBereich1) then FBereich1(self); 
  end else 
    if (d > s1) and (d < s2) and (ib <> 1) then begin 
      ib := 1; 
      if assigned(FBereich2) then FBereich2(self); 
    end else 
      if (d >= s2) and (ib <> 2) then begin 
        ib := 2; 
        if assigned(FBereich3) then FBereich3(self); 
      end; 
end; 
 
procedure TMeter.setValue(d: double); 
begin 
  if (d = FValue) or not enabled then exit; 
  if d < mini then d := mini 
  else if d > maxi then d := maxi; 
  FValue := d; 
  makewert; 
  if assigned(FChange) then FChange(self); 
  makeevent(d); 
  repaint; 
end; 
 
procedure TMeter.setmini(i: integer); 
begin 
  if i = mini then exit; 
  mini := i; 
  Bereich := maxi - mini; 
  if mini > FValue then 
    FValue := mini; 
  makeTeilung; 
  makewert; 
  repaint; 
end; 
 
procedure TMeter.setmaxi(i: integer); 
begin 
  if i = maxi then exit; 
  maxi := i; 
  Bereich := maxi - mini; 
  if maxi < FValue then begin 
    FValue := maxi; 
    makewert; 
  end; 
  makeTeilung; 
  repaint; 
end; 
 
procedure TMeter.setMeterZahlen(m: TMeterZahlen); 
begin 
  if m = FMeterZahlen then exit; 
  FMeterZahlen := m; 
  repaint; 
end; 
 
procedure TMeter.setUntergrund(f: Tcolor); 
begin 
  if f = FUntergrund then exit; 
  FUntergrund := f; 
  repaint; 
end; 
 
procedure TMeter.rechnestriche; 
begin 
  Strichzahl := succ(FTeilung * FBereiche); 
  anz := pred(Strichzahl); 
end; 
 
procedure TMeter.sets1(d: double); 
begin 
  if s1 = d then exit; 
  s1 := d; 
  makeevent(FValue); 
  repaint; 
end; 
 
procedure TMeter.sets2(d: double); 
begin 
  if s2 = d then exit; 
  s2 := d; 
  makeevent(FValue); 
  repaint; 
end; 
 
procedure TMeter.setFarbe1(f: Tcolor); 
begin 
  if FFarbe1 = f then exit; 
  FFarbe1 := f; 
  repaint; 
end; 
 
procedure TMeter.setFarbe2(f: Tcolor); 
begin 
  if FFarbe2 = f then exit; 
  FFarbe2 := f; 
  repaint; 
end; 
 
procedure TMeter.setFarbe3(f: Tcolor); 
begin 
  if FFarbe3 = f then exit; 
  FFarbe3 := f; 
  repaint; 
end; 
 
procedure TMeter.setZeigerfarbe(f: Tcolor); 
begin 
  if FZeigerfarbe = f then exit; 
  FZeigerfarbe := f; 
  repaint; 
end; 
 
procedure TMeter.setWertAnzeige(b: boolean); 
begin 
  if FWertAnzeige = b then exit; 
  FWertAnzeige := b; 
  repaint; 
end; 
 
procedure TMeter.setFaktor(s: single); 
begin 
  if s = FFaktor then exit; 
  FFaktor := s; 
  repaint; 
end; 
 
procedure TMeter.setKommastellen(b: byte); 
begin 
  if b = FStellen then exit; 
  if b > 10 then b := 10; 
  FStellen := b; 
  nk := stringofchar('0', FStellen); 
  repaint; 
end; 
 
procedure TMeter.setEnabled(Value: boolean); 
begin 
  inherited; 
  repaint; 
end; 
 
procedure TMeter.paint; 
var i: integer; 
begin 
  with Canvas do begin 
    brush.color := FUntergrund; 
    FillRect(rect(0, 0, clientwidth, clientheight)); 
    Wert1 := Bereich; 
    Winkel1 := Winkel2; 
    Winkel3 := Winkel2 / anz; 
    for i := 0 to anz do 
    begin 
      x1 := Cos(Winkel1) * Radius1; 
      y1 := Sin(Winkel1) * Radius1; 
      Wert3 := round(Wert1) + mini; 
      if Wert3 >= s2 then pen.color := FFarbe3 
      else if Wert3 <= s1 then pen.color := FFarbe1 
      else pen.color := FFarbe2; 
      if (i mod FTeilung = 0) then begin 
        x2 := x1 + Cos(Winkel1) * Strichgr; 
        y2 := y1 + Sin(Winkel1) * Strichgr; 
        if ((i = 0) or (i = anz)) and (FMeterZahlen <> mKeine) 
          or (FMeterZahlen = mAlle) then begin 
          Canvas.Font.Size := fs; 
          s := inttostr(Wert3); 
          sz := textextent(s); 
          TextOut(Punktx(x2) - pred(sz.cx div 2), Punkty(y2) - sz.cy, s); 
        end; 
      end else begin 
        x2 := x1 + Cos(Winkel1) * Strichkl; 
        y2 := y1 + Sin(Winkel1) * Strichkl; 
      end; 
      Wert1 := Wert1 - Teilung; 
      MoveTo(Punktx(x1), Punkty(y1)); 
      LineTo(Punktx(x2), Punkty(y2)); 
      Winkel1 := Winkel1 + Winkel3; 
    end; 
    if FWertAnzeige then begin 
      Canvas.Font.Size := round(fs * FFaktor); 
      s := formatfloat('#,##0.' + nk, FValue); 
      sz := textextent(s); 
      i := (ClientWidth - sz.cx) div 2; 
      TextOut(i, clientheight - 10 - sz.cy, s); 
    end; 
    if not enabled then exit; 
    Pen.Color := FZeigerfarbe; 
    Winkel1 := Winkel2 + ((Bereich - Wert2) / Bereich) * Winkel2; 
    x1 := Cos(Winkel1) * Radius2; 
    y1 := Sin(Winkel1) * Radius2; 
    x2 := x1 + Cos(Winkel1) * Strich; 
    y2 := y1 + Sin(Winkel1) * Strich; 
    MoveTo(Punktx(x1), Punkty(y1)); 
    LineTo(Punktx(x2), Punkty(y2)); 
  end; 
end; 
 
procedure TMeter.MFont(var Msg: TWMSETFONT); 
begin 
  if not (csReading in componentstate) 
    then begin 
    Canvas.font := Font; 
    fs := Canvas.Font.size; 
    repaint; 
  end; 
end; 
 
end.



 

Zugriffe seit 6.9.2001 auf Delphi-Ecke