Eigene Komponente, Rangeselector um Progressbar erweitern

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
lazarusjulian
Beiträge: 39
Registriert: Mi 6. Jan 2016, 21:45

Eigene Komponente, Rangeselector um Progressbar erweitern

Beitrag von lazarusjulian »

Hallo,
ich habe hier : http://stackoverflow.com/questions/4387 ... -of-values
einen Rangeselector gefunden, also quasi eine Trackbar mit Regler für Anfang und Ende.
Sieht so aus:
Bild
Ich würde gerne zwischen Anfang und Ende noch eine Progressbar setzen, ich habe aber leider keine Ahnung wie ich das anstelle.
Soll also so aussehen:
Bild

Hintergrund ist, dass ich damit mp3-Files schneiden möchte. Die Progressbar dient dazu, die Abspielposition zu zeigen. Beim Verstellen des linken Reglers soll dann immer der Anfang des ausgeschnittenen Stückes abgespielt werden.

Hat vllt Jemand einen Tipp und/oder Tutorial...Ich bin auf dem Gebiet von eigenen Komponenten leider total verloren.

Danke und Gruß
Julian

Warf
Beiträge: 2194
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Eigene Komponente, Rangeselector um Progressbar erweiter

Beitrag von Warf »

Also ich würde einfach eine von TGraphiccontrol Abstammende Komponente Erstellen und die Buttons sowie den Progress selbst zeichnen

lazarusjulian
Beiträge: 39
Registriert: Mi 6. Jan 2016, 21:45

Re: Eigene Komponente, Rangeselector um Progressbar erweiter

Beitrag von lazarusjulian »

Ich weiß es ist peinlich, aber dazu bin ich nicht in der Lage :oops:

Hatte gehofft Jemand ist so nett und macht das für mich (ich weiß, dreist ! :shock: )

oder dass ihr mir dazu Anleitungen verlinkt.

Gruß Julian

Warf
Beiträge: 2194
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Eigene Komponente, Rangeselector um Progressbar erweiter

Beitrag von Warf »

Hier ist der Code einer Trackbar Komponente die ich mal geschrieben habe, kannst dir das mal ansehen

Das Anpassen für deine Bedürfnisse sollte nicht so sehr viel Arbeit sein

Ist letztlich nur ein bisschen 3-Satz Rechnung, und ein wenig Alibi Code drum herum (für Properties, etc)

Code: Alles auswählen

unit MinimalTrackBar;
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs,
  Math, DrawUtils, GraphUtil;
 
type
 
  TTrackButton = (tbNone, tbAuto, tbButton);
 
  TMinimalTrackBar = class(TGraphicControl)
  private
    FLast: integer;
    FOnChange: TNotifyEvent;
    FButtonType: TTrackButton;
    FGrow: boolean;
    FButtonColor: TColor;
    FMouseDown: boolean;
    FMouseOver: boolean;
    FMin, FMax, FPosition: integer;
    FButton3D: boolean;
    procedure SetPosition(x: integer);
    procedure SetMin(x: integer);
    procedure SetMax(x: integer);
    procedure SetButtonColor(x: TColor);
    procedure SetButtonType(x: TTrackButton);
    procedure SetButton3D(x: boolean);
    { Private declarations }
  protected
    procedure Change;
    procedure Paint; override;
    procedure Resize; override;
    procedure MouseEnter; override;
    procedure MouseLeave; override;
    procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
      X: integer; Y: integer); override;
    procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
      X: integer; Y: integer); override;
    procedure MouseMove(Shift: TShiftState; X: integer; Y: integer); override;
    { Protected declarations }
  public
    constructor Create(AOwner: TComponent); override;
    { Public declarations }
  published
    property Button3D: boolean read FButton3D write SetButton3D;
    property OnChange: TNotifyEvent read FOnChange write FOnChange;
    property ButtonType: TTrackButton read FButtonType write SetButtonType;
    property ButtonColor: TColor read FButtonColor write SetButtonColor;
    property Grow: boolean read FGrow write FGrow;
    property MousePressed: boolean read FMouseDown;
    property MouseOver: boolean read FMouseOver;
    property Position: integer read FPosition write SetPosition;
    property Max: integer read FMax write SetMax;
    property Min: integer read FMin write SetMin;
    property Action;
    property Align;
    property Anchors;
    property AutoSize;
    property BidiMode;
    property BorderSpacing;
    property Color;
    property Constraints;
    property DragCursor;
    property DragKind;
    property DragMode;
    property Enabled;
    property Font;
    property ParentBidiMode;
    property OnChangeBounds;
    property OnClick;
    property OnContextPopup;
    property OnDragDrop;
    property OnDragOver;
    property OnEndDrag;
    property OnMouseDown;
    property OnMouseEnter;
    property OnMouseLeave;
    property OnMouseMove;
    property OnMouseUp;
    property OnResize;
    property OnStartDrag;
    property ParentFont;
    property ParentShowHint;
    property PopupMenu;
    property ShowHint;
    property Visible;
  end;
 
procedure Register;
 
implementation
 
procedure TMinimalTrackBar.SetButton3D(x: boolean);
begin
  FButton3D := x;
  Invalidate;
end;
 
procedure TMinimalTrackBar.MouseEnter;
begin
  FMouseOver := True;
  inherited MouseEnter;
  Invalidate;
end;
 
procedure TMinimalTrackBar.MouseLeave;
begin
  FMouseOver := False;
  inherited MouseLeave;
  Invalidate;
end;
 
procedure TMinimalTrackBar.Resize;
begin
  Self.Height := Math.Max(Height, 15);
  Self.Height := Math.Min(Height, Width div 3);
  Invalidate;
  inherited Resize;
end;
 
procedure TMinimalTrackBar.SetPosition(x: integer);
begin
  if (x >= FMin) and (x <= FMax) then
    FPosition := x;
  if (FLast >= FMin) and (FLast <> FPosition) then
    Change;
  FLast := FPosition;
end;
 
procedure TMinimalTrackBar.SetMin(x: integer);
begin
  if FMax - FMin > 0 then
    FMin := x;
  FLast := FMin - 1;
  Invalidate;
end;
 
procedure TMinimalTrackBar.SetMax(x: integer);
begin
  if FMax - FMin > 0 then
    FMax := x;
  FLast := FMin - 1;
  Invalidate;
end;
 
procedure TMinimalTrackBar.SetButtonColor(x: TColor);
begin
  FButtonColor := x;
  Invalidate;
end;
 
procedure TMinimalTrackBar.SetButtonType(x: TTrackButton);
begin
  FButtonType := x;
  Invalidate;
end;
 
procedure TMinimalTrackBar.Change;
begin
  Invalidate;
  if Assigned(FOnChange) then
    FOnChange(Self);
end;
 
procedure TMinimalTrackBar.Paint;
var
  DrawBtn: boolean;
  BarSize: integer;
  r, diff: integer;
begin
  // Zeichenstatus Bestimmen (Größe, Button, etc)
  case FButtonType of
    tbNone:
    begin
      if FGrow then
      begin
        if FMouseOver then
          BarSize := Height
        else
          BarSize := Height div 2;
      end
      else
        BarSize := Height;
      DrawBtn := False;
    end;
    tbAuto:
    begin
      if FGrow then
      begin
        if FMouseOver then
          BarSize := (Height div 2)
        else
          BarSize := Height div 3;
      end
      else
        BarSize := (Height div 2);
      DrawBtn := FMouseOver;
    end;
    tbButton:
    begin
      if FGrow then
      begin
        if FMouseOver then
          BarSize := Height div 2
        else
          BarSize := Height div 3;
      end
      else
        BarSize := Height div 2;
      DrawBtn := True;
    end;
  end;
 
 // Bar Zeichnen
  r := 5;
  if BarSize <= 8 then
    r := BarSize;
  diff := Self.Height - BarSize;
  with Canvas do
  begin
    Brush.Style := bsSolid;
    Pen.Width := 1;
    Pen.Style := psSolid;
    Brush.Color := Math.Max(Math.Min(BlackNWhite(Self.Color), clSilver), $005F5F5F);
    Pen.Color := DarkenColor(Brush.Color, 20);
    RoundRect(Self.Height div 2, diff div 2, Self.Width - (Self.Height div 2),
      Self.Height - diff div 2, r, r);
    if Enabled then
      if MouseOver then
        Brush.Color := LightenColor(Self.Color, 20)
      else
        Brush.Color := Self.Color;
    Pen.Style := psClear;
    RoundRect(Self.Height div 2, diff div 2, Round(
      (FPosition - FMin) / (FMax - FMin) * (Self.Width - Self.Height) +
      Self.Height div 2),
      Self.Height - diff div 2, r, r);
  end;
  // Button Zeichnen
  if DrawBtn and Enabled then
  begin
    if Button3D then
    begin
      if not FMouseDown then
      begin
        r := round(Height / 100 * 15) div 2;
        DrawGradientCircle(Canvas,
          Rect(round((FPosition - FMin) / (FMax - FMin) * (Width - Height)),
          0, round((FPosition - FMin) / (FMax - FMin) * (Width - Height)) +
          (Height), Height),
          GetHighLightColor(ButtonColor),
          GetShadowColor(ButtonColor));
        if (r > 0) then
          DrawGradientCircle(Canvas,
            Rect(round(r + (FPosition - FMin) / (FMax - FMin) * (Width - Height)),
            r, round((FPosition - FMin) / (FMax - FMin) * (Width - Height)) -
            r + (Height), Height - r),
            (ButtonColor),
            GetHighLightColor(ButtonColor));
 
      end
      else
      begin
        r := (Self.Height div 2) div 3 * 2;
        DrawGradientCircle(Canvas,
          Rect(round((FPosition - FMin) / (FMax - FMin) * (Width - Height)),
          0, round((FPosition - FMin) / (FMax - FMin) * (Width - Height)) +
          (Height), Height),
          GetHighLightColor(ButtonColor),
          GetShadowColor(ButtonColor));
        if (r > 0) then
        begin
          Canvas.Brush.Color := GetHighLightColor(ButtonColor);
          Canvas.Ellipse(round((FPosition - FMin) / (FMax - FMin) * (Width - Height)) +
            Height div 4, Height div 4, round((FPosition - FMin) /
            (FMax - FMin) * (Width - Height)) + (Height - Height div 4),
            Height - Height div 4);
        end;
      end;
    end
    else
      DrawGradientCircle(Canvas, Rect(round(FPosition / 100 * (Width - Height)),
        0, round(FPosition / 100 * (Width - Height)) + (Height), Height),
        (ButtonColor),
        GetShadowColor(ButtonColor));
 
  end;
 
  inherited Paint;
end;
 
procedure TMinimalTrackBar.MouseDown(Button: TMouseButton; Shift: TShiftState;
  X: integer; Y: integer);
begin
  // Wenn Geklickt wird
  if Button = mbLeft then
  begin  // Neue Position am Cursor Punkt
    FPosition := Math.Max(Min, Math.Min(Max, round(
      ((X - Height / 2) / (Width - Height)) * (Max - Min) + Min)));
    FMouseDown := True;
    Change;
  end;
  FMouseOver := True;
 
  inherited MouseDown(Button, Shift, X, Y);
end;
 
procedure TMinimalTrackBar.MouseUp(Button: TMouseButton; Shift: TShiftState;
  X: integer; Y: integer);
begin
  if Button = mbLeft then
  begin // Neue Position am Cursor Punkt
    FPosition := Math.Max(Min, Math.Min(Max, round(
      ((X - Height / 2) / (Width - Height)) * (Max - Min) + Min)));
    Change;
    FMouseDown := False;
  end;
  FMouseOver := (x > 0) and (x < Width) and (y > 0) and (y < Height);
 
  inherited MouseUp(Button, Shift, X, Y);
end;
 
procedure TMinimalTrackBar.MouseMove(Shift: TShiftState; X: integer; Y: integer);
begin
  if ssLeft in Shift then
  begin // Neue Position am Cursor Punkt
    FPosition := Math.Max(Min, Math.Min(Max, round(
      ((X - Height / 2) / (Width - Height)) * (Max - Min) + Min)));
    FMouseDown := True;
    Change;
  end
  else if FMouseDown then
    FMouseDown := False;
 
  FMouseOver := True;
 
  inherited MouseMove(Shift, X, Y);
end;
 
constructor TMinimalTrackBar.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  SetInitialBounds(0, 0, 75, 15);
  FMax := 100;
  FMin := 0;
  FPosition := 50;
  FLast := FMin - 1;
  ButtonColor := clSilver;
  Color := $00c39157;
  FGrow := True;
  FButton3D := True;
  ButtonType := tbAuto;
  FMouseOver := False;
  Cursor := crHandPoint;
end;
 
procedure Register;
begin
  {$I minimaltrackbar_icon.lrs}
  RegisterComponents('Minimal Components', [TMinimalTrackBar]);
end;
 
end.

lazarusjulian
Beiträge: 39
Registriert: Mi 6. Jan 2016, 21:45

Re: Eigene Komponente, Rangeselector um Progressbar erweiter

Beitrag von lazarusjulian »

Danke, leider kann mein Lazarus die Unit DrawUtils nicht finden. Wo gibt's die ?

LG Julian

Warf
Beiträge: 2194
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Eigene Komponente, Rangeselector um Progressbar erweiter

Beitrag von Warf »

Ist ne eigene Unit:

Code: Alles auswählen

unit DrawUtils;
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, Graphics, Math, LCLType, GraphUtil;
 
type
  TPercent = 0..100;
  TRGB = packed record
    case byte of
      0: (R, G, B: byte);
      1: (Color: TColor);
  end;
 
  THLS = packed record
    H,S: Byte;
    case boolean of
      True: (V: byte);
      False: (L: byte);
  end;
  THSV=THLS;
 
function LightenColor(c: TColor; Val: TPercent): TColor;
function DarkenColor(c: TColor; Val: TPercent): TColor;
function BlackNWhite(c: TColor): TColor;
procedure DrawTextCenter(c: TCanvas; Width, Height: integer; Caption: string);
function RGBtoHSV(Col: TColor): THSV;
function HSVtoRGB(HSV: THSV): TColor;
procedure DrawGradientCircle(Canvas: TCanvas; ARect: TRect;
  Color1, Color2: TColor; Vert: boolean = True); overload;
procedure DrawGradientCircle(Canvas: TCanvas; Left, Top, Radius: Integer;
  Color1, Color2: TColor; Vert: boolean = True); overload;
procedure DrawRadient(Canvas: TCanvas; Left, Top, Radius: Integer; Color1, Color2: TColor);
procedure FillRadient(Canvas: TCanvas; ARect: TRect; Color1, Color2: TColor);
procedure DrawCircle(Canvas: TCanvas; Left, Top, Radius: Integer); inline;
procedure DrawOpacity(PosX, PosY: Integer; c: TCanvas; g: TGraphic; Opac: double);
 
implementation
 
procedure DrawOpacity(PosX, PosY: integer; c: TCanvas; g: TGraphic; Opac: double);
var
  x, y: integer;
  bmp: TBitmap;
  r, r2: TRGB;
begin
  bmp := TBitmap.Create;
  try
    bmp.Assign(g);
    for y := 0 to bmp.Height do
      for x := 0 to bmp.Width do
      begin
        r.Color := c.Pixels[PosX + X, PosY + y];
        r2.Color := bmp.Canvas.Pixels[X, Y];
        r.R:=round(r.R*(1-Opac)+r2.R*Opac);
        r.G:=round(r.G*(1-Opac)+r2.G*Opac);
        r.B:=round(r.B*(1-Opac)+r2.B*Opac);
        c.Pixels[PosX + X, PosY + y]:=r.Color;
      end;
  finally
    bmp.Free;
  end;
end;
 
procedure DrawCircle(Canvas: TCanvas; Left, Top, Radius: Integer); inline;
begin
  Canvas.Ellipse(Left-Radius, Top-Radius, Left+Radius, Top+Radius);
end;
 
procedure DrawRadient(Canvas: TCanvas; Left, Top, Radius: Integer; Color1, Color2: TColor);
  function GetColVal(C1, C2, F1, F2: Integer): TColor;
  var r1, r2, res: TRGB;
  begin
    r1.Color:=C1;
    r2.Color:=C2;
    res.r := Round(r1.r + (r2.r - r1.r) * F1 / (F2));
    res.g := Round(r1.g + (r2.g - r1.g) * F1 / (F2));
    res.b := Round(r1.b + (r2.b - r1.b) * F1 / (F2));
    Result:=res.Color;
  end;
 
var i: Integer;
begin
  for i := Radius downto 0 do
  begin
    Canvas.Brush.Color:=GetColVal(Color2, Color1, i, Radius);
    Canvas.Brush.Style:=bsSolid;
    Canvas.Pen.Style:=psClear;
    DrawCircle(Canvas, Left, Top, i);
  end;
end;
 
procedure FillRadient(Canvas: TCanvas; ARect: TRect; Color1, Color2: TColor);
var bmp: TBitmap;
begin
  bmp:=TBitmap.Create;
  try
    bmp.Width:=ARect.Right-ARect.Left;
    bmp.Height:=ARect.Bottom-ARect.Top;
    DrawRadient(bmp.Canvas, bmp.Width div 2, bmp.Height div 2,
      round(sqrt(bmp.Height**2 + bmp.Width**2) / 2), Color1, Color2);
    Canvas.Draw(ARect.Left, ARect.Top, bmp);
  finally
    bmp.Free;
  end;
end;
 
procedure DrawGradientCircle(Canvas: TCanvas; Left, Top, Radius: Integer;
  Color1, Color2: TColor; Vert: boolean = True);
begin
  DrawGradientCircle(Canvas, Rect(Left-Radius, Top-Radius,
    Left+Radius, Top+Radius), Color1, Color2, Vert);
end;
 
procedure DrawGradientCircle(Canvas: TCanvas; ARect: TRect;
  Color1, Color2: TColor; Vert: boolean = True);
  function GetRectV(Circle: TRect; Position: integer): TRect;
  var
    Mid, Wid, r: integer;
  begin
    Mid := (Circle.Right + Circle.Left) div 2;
    r := abs(Circle.Right - Circle.Left) div 2;
    Wid := trunc(sqrt(sqr(r) - sqr(Position - r)));
    if Position - r = 0 then
      wid -= 1;
    if Wid = 1 then
      Wid := 0;
    Result.Top := Position + Circle.Top;
    Result.Bottom := Result.Top + 1;
    Result.Left := Mid - Wid;
    Result.Right := Mid + Wid;
  end;
 
  function GetRectH(Circle: TRect; Position: integer): TRect;
  var
    Mid, Wid, r: integer;
  begin
    Mid := (Circle.Bottom + Circle.Top) div 2;
    r := abs(Circle.Bottom - Circle.Top) div 2;
    Wid := trunc(sqrt(sqr(r) - sqr(Position - r)));
    if Position - r = 0 then
      wid -= 1;
    if Wid = 1 then
      Wid := 0;
    Result.Left := Position + Circle.Left;
    Result.Right := Result.Left + 1;
    Result.Top := Mid - Wid;
    Result.Bottom := Mid + Wid;
  end;
 
var
  c1, c2, c: TRGB;  //for easy access to RGB values as well as TColor value
  x, y: integer;         //current pixel position to be set
  OldPenWidth: integer;  //Save old settings to restore them properly
  OldPenStyle: TPenStyle;//see above
begin
  c1.Color := ColorToRGB(Color1);  //convert system colors to RGB values
  c2.Color := ColorToRGB(Color2);  //if neccessary
  OldPenWidth := Canvas.Pen.Width; //get old settings
  OldPenStyle := Canvas.Pen.Style;
  Canvas.Pen.Width := 1;             //ensure correct pen settings
  Canvas.Pen.Style := psInsideFrame;
 
  case Vert of
    True:
    begin
      for y := 0 to ARect.Bottom - ARect.Top do
      begin
        c.r := Round(c1.r + (c2.r - c1.r) * y / (ARect.Bottom - ARect.Top));
        c.g := Round(c1.g + (c2.g - c1.g) * y / (ARect.Bottom - ARect.Top));
        c.b := Round(c1.b + (c2.b - c1.b) * y / (ARect.Bottom - ARect.Top));
        Canvas.Brush.Color := c.Color;
        Canvas.FillRect(GetRectV(ARect, y));
      end;
    end;
    False:
    begin
      for x := 0 to ARect.Right - ARect.Left do
      begin
        c.r := Round(c1.r + (c2.r - c1.r) * x / (ARect.Right - ARect.Left));
        c.g := Round(c1.g + (c2.g - c1.g) * x / (ARect.Right - ARect.Left));
        c.b := Round(c1.b + (c2.b - c1.b) * x / (ARect.Right - ARect.Left));
        Canvas.Brush.Color := c.Color;
        Canvas.FillRect(GetRectH(ARect, x));
      end;
    end;
  end;
  Canvas.Pen.Width := OldPenWidth; //restore old settings
  Canvas.Pen.Style := OldPenStyle;
end;
 
function RGBtoHSV(Col: TColor): THSV;
begin
  ColorToHLS(Col, Result.h, Result.L, Result.S);
end;
 
function HSVtoRGB(HSV: THSV): TColor;
begin
  Result:=HLStoColor(HSV.H, HSV.L, HSV.S);
end;
 
function BlackNWhite(c: TColor): TColor;
var
  H: THSV;
begin
  H := RGBtoHSV(c);
  H.S := 0;
  Result := HSVtoRGB(H);
end;
 
procedure DrawTextCenter(c: TCanvas; Width, Height: integer; Caption: string);
begin
  c.TextOut((Width div 2) - (c.TextWidth(Caption) div 2),
    (Height div 2) - (c.TextHeight(Caption) div 2), Caption);
end;
 
function LightenColor(c: TColor; Val: TPercent): TColor;
var
  h: THSV;
  o: Byte;
begin
  h := RGBtoHSV(ColorToRGB(c));
  o:=h.V;
  h.v := h.v + h.v div 100 * Val;
  if h.v<o then
    h.v:=255;
  Result := HSVtoRGB(h);
end;
 
function DarkenColor(c: TColor; Val: TPercent): TColor;
var
  h: THSV;
  o: Byte;
begin
  h := RGBtoHSV(ColorToRGB(c));
  o:=h.V;
  h.v := h.v - h.v div 100 * Val;
  if h.v>o then
    h.v:=0;
  Result := HSVtoRGB(h);
end;
 
end.

lazarusjulian
Beiträge: 39
Registriert: Mi 6. Jan 2016, 21:45

Re: Eigene Komponente, Rangeselector um Progressbar erweiter

Beitrag von lazarusjulian »

Danke. Naja eben dieser Alibi Code drumrum ist so überhaupt nicht meine Sache. Denke das hängt einfach damit zusammen dass ich mich noch nicht genug mit Klassen und Vererbung beschäftigt habe.


LG Julian

Antworten