⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vrmeter.pas

📁 作工控的好控件
💻 PAS
字号:
{*****************************************************}
{                                                     }
{     Varian Component Workshop                       }
{                                                     }
{     Varian Software NL (c) 1996-2000                }
{     All Rights Reserved                             }
{                                                     }
{*****************************************************}

unit VrMeter;

{$I VRLIB.INC}

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  VrClasses, VrControls, VrSysUtils;

type
  TVrMeter = class;

  TVrMeterScale = class(TVrPersistent)
  private
    FColor1: TColor;
    FColor2: TColor;
    FColor3: TColor;
    FEnlarge: Integer;
    FPercent1: Integer;
    FPercent2: Integer;
    FTicks: Integer;
    FHeightMax: Integer;
    FHeightMin: Integer;
    FVisible: Boolean;
    Owner: TVrMeter;
    procedure SetColor1(Value: TColor);
    procedure SetColor2(Value: TColor);
    procedure SetColor3(Value: TColor);
    procedure SetEnlarge(Value: Integer);
    procedure SetPercent1(Value: Integer);
    procedure SetPercent2(Value: Integer);
    procedure SetTicks(Value: Integer);
    procedure SetHeightMax(Value: Integer);
    procedure SetHeightMin(Value: Integer);
    procedure SetVisible(Value: Boolean);
  public
    constructor Create;
  published
    property Color1: TColor read FColor1 write SetColor1 default clGreen;
    property Color2: TColor read FColor2 write SetColor2 default clYellow;
    property Color3: TColor read FColor3 write SetColor3 default clRed;
    property Enlarge: Integer read FEnlarge write SetEnlarge default 5;
    property Percent1: Integer read FPercent1 write SetPercent1 default 61;
    property Percent2: Integer read FPercent2 write SetPercent2 default 25;
    property Ticks: Integer read FTicks write SetTicks default 60;
    property HeightMax: Integer read FHeightMax write SetHeightMax default 8;
    property HeightMin: Integer read FHeightMin write SetHeightMin default 5;
    property Visible: Boolean read FVisible write SetVisible default True;
  end;

  TVrMeter = class(TVrGraphicImageControl)
  private
    FAngle: Integer;
    FScale: TVrMeterScale;
    FMinValue: Integer;
    FMaxValue: Integer;
    FPosition: Integer;
    FNeedleColor: TColor;
    FNeedleWidth: Integer;
    FSpacing: Integer;
    FLabels: Integer;
    FLabelOffsetX: Integer;
    FLabelOffsetY: Integer;
    FBevel: TVrBevel;
    FBackImage: TBitmap;
    FCenter: TPoint;
    FRadius: Integer;
    procedure SetAngle(Value: Integer);
    procedure SetMinValue(Value: Integer);
    procedure SetMaxValue(Value: Integer);
    procedure SetPosition(Value: Integer);
    procedure SetNeedleColor(Value: TColor);
    procedure SetNeedleWidth(Value: Integer);
    procedure SetBevel(Value: TVrBevel);
    procedure SetSpacing(Value: Integer);
    procedure SetLabels(Value: Integer);
    procedure SetLabelOffsetX(Value: Integer);
    procedure SetLabelOffsetY(Value: Integer);
    procedure SetBackImage(Value: TBitmap);
    procedure BevelChanged(Sender: TObject);
    procedure ScaleChanged(Sender: TObject);
    procedure BackImageChanged(Sender: TObject);
    procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED;
  protected
    procedure DrawScale;
    procedure DrawNeedle;
    procedure DrawLabels;
    procedure Paint; override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
  published
    property MaxValue: Integer read FMaxValue write SetMaxValue default 100;
    property MinValue: Integer read FMinValue write SetMinValue default 0;
    property Position: Integer read FPosition write SetPosition default 0;
    property Angle: Integer read FAngle write SetAngle default 40;
    property Scale: TVrMeterScale read FScale write FScale;
    property NeedleColor: TColor read FNeedleColor write SetNeedleColor default clSilver;
    property NeedleWidth: Integer read FNeedleWidth write SetNeedleWidth default 1;
    property Bevel: TVrBevel read FBevel write SetBevel;
    property Spacing: Integer read FSpacing write SetSpacing default 20;
    property Labels: Integer read FLabels write SetLabels default 10;
    property LabelOffsetX: Integer read FLabelOffsetX write SetLabelOffsetX default 15;
    property LabelOffsetY: Integer read FLabelOffsetY write SetLabelOffsetY default 10;
    property BackImage: TBitmap read FBackImage write SetBackImage;
    property Align;
{$IFDEF VER110}
    property Anchors;
    property Constraints;
{$ENDIF}
    property Caption;
    property Color;
    property DragCursor;
{$IFDEF VER110}
    property DragKind;
{$ENDIF}
    property DragMode;
    property Font;
    property Hint;
    property ParentColor;
    property ParentShowHint;
    property PopupMenu;
    property ParentFont;
    property ShowHint;
    property Visible;
    property OnClick;
{$IFDEF VER130}
    property OnContextPopup;
{$ENDIF}
    property OnDblClick;
    property OnDragDrop;
    property OnDragOver;
{$IFDEF VER110}
    property OnEndDock;
{$ENDIF}
    property OnEndDrag;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
{$IFDEF VER110}
    property OnStartDock;
{$ENDIF}
    property OnStartDrag;
  end;



implementation

function DegToRad(Degrees: Extended): Extended;
begin
  Result := Degrees * (PI / 180);
end;

{ TVrMeterScale }

constructor TVrMeterScale.Create;
begin
  inherited Create;
  FColor1 := clGreen;
  FColor2 := clYellow;
  FColor3 := clRed;
  FEnlarge := 5;
  FPercent1 := 60;
  FPercent2 := 25;
  FTicks := 61;
  FHeightMax := 8;
  FHeightMin := 5;
  FVisible := True
end;

procedure TVrMeterScale.SetColor1(Value: TColor);
begin
  if FColor1 <> Value then
  begin
    FColor1 := Value;
    Changed;
  end;
end;

procedure TVrMeterScale.SetColor2(Value: TColor);
begin
  if FColor2 <> Value then
  begin
    FColor2 := Value;
    Changed;
  end;
end;

procedure TVrMeterScale.SetColor3(Value: TColor);
begin
  if FColor3 <> Value then
  begin
    FColor3 := Value;
    Changed;
  end;
end;

procedure TVrMeterScale.SetEnlarge(Value: Integer);
begin
  if FEnlarge <> Value then
  begin
    FEnlarge := Value;
    Changed;
  end;
end;

procedure TVrMeterScale.SetPercent1(Value: Integer);
begin
  if (FPercent1 <> Value) then
  begin
    if not Owner.Loading then
      if Value + Percent2 > 100 then Value := 100 - Percent2;
    FPercent1 := Value;
    Changed;
  end;
end;

procedure TVrMeterScale.SetPercent2(Value: Integer);
begin
  if (FPercent2 <> Value) and (Value + Percent1 <= 100) then
  begin
    if not Owner.Loading then
      if Value + Percent1 > 100 then Value := 100 - Percent1;
    FPercent2 := Value;
    Changed;
  end;
end;

procedure TVrMeterScale.SetTicks(Value: Integer);
begin
  if FTicks <> Value then
  begin
    FTicks := Value;
    Changed;
  end;
end;

procedure TVrMeterScale.SetHeightMax(Value: Integer);
begin
  if FHeightMax <> Value then
  begin
    FHeightMax := Value;
    Changed;
  end;
end;

procedure TVrMeterScale.SetHeightMin(Value: Integer);
begin
  if FHeightMin <> Value then
  begin
    FHeightMin := Value;
    Changed;
  end;
end;

procedure TVrMeterScale.SetVisible(Value: Boolean);
begin
  if FVisible <> Value then
  begin
    FVisible := Value;
    Changed;
  end;
end;

{ TVrMeter }

constructor TVrMeter.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  ControlStyle := ControlStyle + [csOpaque];
  Width := 240;
  Height := 115;
  Color := clBlack;
  ParentColor := false;
  with Font do
  begin
    Name := 'Arial';
    Size := 8;
    Color := clSilver;
  end;
  FAngle := 40;
  FMinValue := 0;
  FMaxValue := 100;
  FPosition := 0;
  FNeedleColor := clSilver;
  FNeedleWidth := 1;
  FSpacing := 20;
  FLabels := 10;
  FLabelOffsetX := 15;
  FLabelOffsetY := 10;
  FBevel := TVrBevel.Create;
  with FBevel do
  begin
    InnerStyle := bsLowered;
    InnerWidth := 2;
    InnerColor := clBlack;
    OnChange := BevelChanged;
  end;
  FScale := TVrMeterScale.Create;
  FScale.Owner := Self;
  FScale.OnChange := ScaleChanged;
  FBackImage := TBitmap.Create;
  FBackImage.OnChange := BackImageChanged;
end;

destructor TVrMeter.Destroy;
begin
  FScale.Free;
  FBevel.Free;
  FBackImage.Free;
  inherited Destroy;
end;

procedure TVrMeter.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
begin
  FRadius := AHeight - 10;
  FCenter.X := AWidth div 2;
  FCenter.Y := AHeight + FSpacing;
  inherited SetBounds(ALeft, ATop, AWidth, AHeight);
end;

procedure TVrMeter.DrawScale;
var
  sX, sY, eX, eY: Integer;
  I, sAngle, eAngle: Integer;
  Ticks, TickHeight, Enlarge: Integer;
  Point, Point1, Point2: Integer;
  Offset, Step: Extended;
begin
  Ticks := Scale.Ticks;
  Enlarge := Scale.Enlarge;

  sAngle := 270 + FAngle;
  eAngle := sAngle + 180 - FAngle * 2;
  Step := (eAngle - sAngle)/Ticks;

  Point := 0;
  Point1 := SolveForX(Scale.Percent1, Scale.Ticks);
  Point2 := Point1 + SolveForX(Scale.Percent2, Scale.Ticks);

  with BitmapCanvas do
  begin
    Pen.Mode := pmCOPY;
    Pen.Width := 1;
    for I := 0 to Ticks - 1 do
    begin
      Inc(Point);
      if Point <= Point1 then Pen.Color := Scale.Color1
      else if Point <= Point2 then Pen.Color := Scale.Color2
      else Pen.Color := Scale.Color3;
      if Enlarge = Scale.Enlarge then TickHeight := Scale.HeightMax
      else TickHeight := Scale.HeightMin;
      Offset := DegToRad(sAngle + I * Step);
      sX := FCenter.X + Trunc(Sin(Offset) * (FRadius - Scale.HeightMin));
      sY := FCenter.Y + Trunc(Cos(Offset) * (FRadius - Scale.HeightMin));

      eX := FCenter.X + Trunc(Sin(Offset) *
            (FRadius + TickHeight - Scale.HeightMin));
      eY := FCenter.Y + Trunc(Cos(Offset) *
            (FRadius + TickHeight - Scale.HeightMin));
      MoveTo(sX, FCenter.Y * 2 - sY);
      LineTo(eX, FCenter.Y * 2 - eY);
      if Enlarge < Scale.Enlarge then Inc(Enlarge) else Enlarge := 1;
    end;
  end;
end;

procedure TVrMeter.DrawNeedle;
var
  X, Y, Ticks: Integer;
  P: Integer;
  Offset, Step: Extended;
  sAngle, eAngle: Integer;
begin
  Ticks := Scale.Ticks;
  sAngle := 270 + FAngle;
  eAngle := sAngle + 180 - FAngle * 2;
  Step := (eAngle - sAngle)/Ticks;
  P := Trunc((Position / (MaxValue - MinValue)) * Pred(Ticks));

  with BitmapCanvas do
  begin
    Pen.Mode := pmCOPY;
    Pen.Color := FNeedleColor;
    Pen.Width := FNeedleWidth;
    Offset := DegToRad(sAngle + P * Step);
    X := FCenter.X + Trunc(Sin(Offset) * FRadius);
    Y := FCenter.Y + Trunc(Cos(Offset) * FRadius);
    MoveTo(FCenter.X, FCenter.Y);
    LineTo(X, FCenter.Y * 2 - Y);
  end;
end;

procedure TVrMeter.DrawLabels;
var
  X, Y, Ticks, I, LabelCnt, LC, LV: Integer;
  str: string;
  Offset, Step, BaseValue: Extended;
  sAngle, eAngle, Adjust: Integer;
  TextSize: TSize;
begin
  Ticks := Scale.Ticks;
  sAngle := 270 + FAngle;
  eAngle := sAngle + 180 - FAngle * 2;
  Step := (eAngle - sAngle) / Scale.Ticks;
  BaseValue := (FMaxValue - FMinValue) / Labels;

  LabelCnt := (Scale.Ticks div Labels)-1;
  LC := 0;
  LV := -1;
  with BitmapCanvas do
  begin
    Font.Assign(Self.Font);
    Brush.Style := bsClear;
    for I := 0 to Ticks - 1 do
    begin
      if LC = 0 then
      begin
        Inc(LV);
        str := IntToStr(FMinValue + Round(BaseValue * LV));
        TextSize := TextExtent(str);
        Offset := DegToRad(sAngle + I * Step);
        X := FCenter.X + Trunc(Sin(Offset) *
             (FRadius + Scale.HeightMax - Scale.HeightMin + LabelOffsetX));
        Y := FCenter.Y + Trunc(Cos(Offset) *
             (FRadius + Scale.HeightMax - Scale.HeightMin + LabelOffsetY));

        Adjust := X - (TextSize.cX div 2);
        Y := Y + (TextSize.cY div 2);
        TextOut(Adjust, FCenter.Y * 2 - Y, str);
      end;
      if LC = 0 then LC := LabelCnt else Dec(LC);
    end;
  end;
end;

procedure TVrMeter.Paint;
var
  X: Integer;
  BevelRect: TRect;
begin
  ClearBitmapCanvas;

  if not FBackImage.Empty then
    BitmapCanvas.StretchDraw(ClientRect, FBackImage);

  if Scale.Visible then DrawScale;
  if Labels > 0 then DrawLabels;
  DrawNeedle;

  BevelRect := ClientRect;
  FBevel.GetVisibleArea(BevelRect);
  with BitmapCanvas do
  begin
    Font.Assign(Self.Font);
    X := FCenter.X - (TextWidth(Caption) div 2);
    TextOut(X, BevelRect.Bottom - 10 - TextHeight(Caption), Caption);
  end;

  BevelRect := ClientRect;
  FBevel.Paint(BitmapCanvas, BevelRect);
  inherited Paint;
end;

procedure TVrMeter.ScaleChanged(Sender: TObject);
begin
  UpdateControlCanvas;
end;

procedure TVrMeter.SetAngle(Value: Integer);
begin
  if FAngle <> Value then
  begin
    FAngle := Value;
    UpdateControlCanvas;
  end;
end;

procedure TVrMeter.SetMinValue(Value: Integer);
begin
  if (FMinValue <> Value) and (Value < FMaxValue) then
  begin
    FMinValue := Value;
    UpdateControlCanvas;
  end;
end;

procedure TVrMeter.SetMaxValue(Value: Integer);
begin
  if (FMaxValue <> Value) and (Value > FMinValue) then
  begin
    FMaxValue := Value;
    UpdateControlCanvas;
  end;
end;

procedure TVrMeter.SetPosition(Value: Integer);
begin
  AdjustRange(Value, FMinValue, FMaxValue);
  if (FPosition <> Value) then
  begin
    FPosition := Value;
    UpdateControlCanvas;
  end;
end;

procedure TVrMeter.SetNeedleColor(Value: TColor);
begin
  if FNeedleColor <> Value then
  begin
    FNeedleColor := Value;
    UpdateControlCanvas;
  end;
end;

procedure TVrMeter.SetNeedleWidth(Value: Integer);
begin
  if FNeedleWidth <> Value then
  begin
    FNeedleWidth := Value;
    UpdateControlCanvas;
  end;
end;

procedure TVrMeter.SetBevel(Value: TVrBevel);
begin
  FBevel.Assign(Value);
end;

procedure TVrMeter.BevelChanged(Sender: TObject);
begin
  UpdateControlCanvas;
end;

procedure TVrMeter.SetSpacing(Value: Integer);
begin
  if FSpacing <> Value then
  begin
    FSpacing := Value;
    FCenter.Y := Height + Value;
    UpdateControlCanvas;
  end;
end;

procedure TVrMeter.SetLabels(Value: Integer);
begin
  if FLabels <> Value then
  begin
    FLabels := Value;
    UpdateControlCanvas;
  end;
end;

procedure TVrMeter.SetLabelOffsetX(Value: Integer);
begin
  if FLabelOffsetX <> Value then
  begin
    FLabelOffsetX := Value;
    UpdateControlCanvas;
  end;
end;

procedure TVrMeter.SetLabelOffsetY(Value: Integer);
begin
  if FLabelOffsetY <> Value then
  begin
    FLabelOffsetY := Value;
    UpdateControlCanvas;
  end;
end;

procedure TVrMeter.CMTextChanged(var Message: TMessage);
begin
  inherited;
  UpdateControlCanvas;
end;

procedure TVrMeter.BackImageChanged(Sender: TObject);
begin
  UpdateControlCanvas;
end;

procedure TVrMeter.SetBackImage(Value: TBitmap);
begin
  FBackImage.Assign(Value);
end;



end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -