// Angeregt durch eine Frage in einem Delphi-Forum entstand der folgende Code
// für einen Schieberegler mit zwei Schiebern.

Bild 1 Bild 2 Bild 3 Bild 4 Bild 5

// Getestet mit D4 unter XP

unit DblSlider; 
 
interface 
 
uses 
  Windows, SysUtils, Classes, Graphics, Controls, ExtCtrls, Stdctrls; 
 
type 
  TLftRght = (dblLeft, dblRight); 
  TBvl = (dblFlat, dblLowered, dblRaised); 
  TInd = (dblNone, dblMinMax, dblPos1Pos2); 
  TGivePos = procedure(Sender: TObject; Min, BandLinks, Pos1, BandMitte, Pos2, 
    BandRechts, Max: Integer) of object; 
  TGiveSlide = procedure(Sender: TObject; Wich: TLftRght; Pos1, Pos2: Integer) 
    of object; 
  TDblSlider = class(TCustomPanel) 
  private 
    art: TBvl; 
    p: TPoint; 
    tcl: TLabel; 
    trsp: TColor; 
    indktn: TInd; 
    abst: single; 
    FPosChange: TGivePos; 
    FMouseUp: TGiveSlide; 
    FMouseDown: TGiveSlide; 
    lbl: array[0..1] of TLabel; 
    Schieber: array[0..1] of TImage; 
    isdown, einmal, zeiger, rOK, mOK, nhint, mhint: boolean; 
    diffw, diffs, mini, maxi, poslinks, posrechts, links, breite, 
      schieberbreite, schieberhoehe, f, hoehe, skala, lks, rts, rand, 
      anzeige: integer; 
  protected 
    procedure tw; 
    procedure rfbs; 
    procedure werte; 
    procedure lbltop; 
    procedure feuern; 
    procedure testen; 
    procedure posit1; 
    procedure posit2; 
    procedure malzeiger; 
    procedure makelinks; 
    procedure lblrechts; 
    procedure makerechts; 
    procedure rechnefreq; 
    procedure linksrechts; 
    procedure beidesetzen; 
    procedure setind(i: TInd); 
    procedure setbevel(bv: TBvl); 
    procedure setMin(i: integer); 
    procedure setMax(i: integer); 
    procedure setzen(img: Timage); 
    procedure setAbst(i: integer); 
    procedure setPosL(i: integer); 
    procedure setPosR(i: integer); 
    procedure setnhint(b: boolean); 
    procedure rechnen(img: Timage); 
    procedure setzeiger(b: boolean); 
    procedure festlegen(img: Timage); 
    procedure verschieben(img: Timage); 
    procedure positionieren(img: Timage); 
    procedure zahlzeigen(Sender: TImage); 
    procedure XMouseDown(Sender: TObject; Button: TMouseButton; 
      Shift: TShiftState; X, Y: Integer); 
    procedure XMouseUp(Sender: TObject; Button: TMouseButton; 
      Shift: TShiftState; X, Y: Integer); 
    procedure XMouseMove(Sender: TObject; Shift: TShiftState; 
      X, Y: Integer); 
    procedure paint; override; 
    procedure Resize; override; 
  public 
    constructor Create(Owner: TComponent); override; 
    destructor Destroy; override; 
  published 
    property ShowHint; 
    property Bevel: TBvl read art write setbevel; 
    property Max: integer read maxi write setmax; 
    property Min: integer read mini write setmin; 
    property Frequency: integer read f write setAbst; 
    property Indicator: TInd read indktn write setind; 
    property Scale: boolean read zeiger write setzeiger; 
    property PositionDsp: boolean read nhint write setnhint; 
    property Position1: integer read poslinks write setPosL; 
    property Position2: integer read posrechts write setPosR; 
    property OnSldMouseUp: TGiveSlide read FMouseUp write FMouseUp; 
    property OnPosChange: TGivePos read FPosChange write FPosChange; 
    property OnSldMouseDown: TGiveSlide read FMouseDown write FMouseDown; 
  end; 
 
procedure Register; 
 
implementation 
 
constructor TDblSlider.Create(Owner: TComponent); 
var x, y: integer; 
begin 
  inherited Create(Owner); 
  doublebuffered := true; 
  parentcolor := true; 
  parentfont := false; 
  with canvas do begin 
    Font.Name := 'Arial'; 
    Font.size := 9; 
  end; 
  art := dblRaised; 
  zeiger := true; 
  einmal := true; 
  nhint := true; 
  mhint := true; 
  skala := 7; 
  anzeige := 9; 
  breite := 129; 
  hoehe := 29; 
  rand := 8; 
  schieberbreite := 7; 
  schieberhoehe := 13; 
  mini := 0; 
  maxi := 100; 
  f := 5; 
  abst := 5; 
  height := hoehe; 
  width := breite; 
  for x := 0 to 1 do begin 
    Schieber[x] := TImage.create(self); 
    lbl[x] := TLabel.create(self); 
    lbl[x].parent := self; 
    with Schieber[x] do begin 
      parent := self; 
      autosize := true; 
      with picture.bitmap, canvas do begin 
        cursor := crHandpoint; 
        onMouseDown := XMouseDown; 
        onMouseMove := XMouseMove; 
        onMouseUp := XMouseUp; 
        width := schieberbreite; 
        height := schieberhoehe; 
        brush.color := clGray; 
        rectangle(0, 3, width, height); 
        brush.color := clWhite; 
        fillrect(rect(1, 4, pred(schieberbreite), 6)); 
        brush.color := $404040; 
        fillrect(rect(1, 7, pred(schieberbreite), pred(schieberhoehe))); 
        for y := 0 to 2 do begin 
          moveto(y * 2 + 2, 4); 
          lineto(y * 2 + 2, height); 
        end; 
      end; 
    end; 
  end; 
  trsp := Color; 
  malzeiger; 
  poslinks := 0; 
  posrechts := maxi; 
  lbl[0].left := rand + 1; 
  tcl := TLabel.create(self); 
  tcl.parent := self; 
  tcl.left := -maxint; 
end; 
 
destructor TDblSlider.Destroy; 
var x: integer; 
begin 
  tcl.free; 
  for x := 0 to 1 do begin 
    Schieber[x].free; 
    lbl[x].free; 
  end; 
  inherited Destroy; 
end; 
 
procedure TDblSlider.linksrechts; 
begin 
  lks := rand + schieberbreite - 1; 
  rts := width - lks - 1; 
end; 
 
procedure TDblSlider.werte; 
begin 
  case ord(indktn = dblPos1Pos2) of 
    1: begin 
        lbl[0].caption := inttostr(poslinks); 
        lbl[1].caption := inttostr(posrechts); 
      end; 
  else begin 
      lbl[0].caption := inttostr(mini); 
      lbl[1].caption := inttostr(maxi); 
    end; 
  end; 
end; 
 
procedure TDblSlider.lblrechts; 
begin 
  lbl[1].left := width - 1 - rand - lbl[1].width; 
end; 
 
procedure TDblSlider.tw; 
begin 
  testen; 
  werte; 
end; 
 
procedure TDblSlider.feuern; 
begin 
  tw; 
  lblrechts; 
  if assigned(FPosChange) then begin 
    FPosChange(self, mini, poslinks - mini, poslinks, posrechts - poslinks, 
      posrechts, maxi - posrechts, maxi); 
    einmal := false; 
  end; 
end; 
 
procedure TDblSlider.lbltop; 
var x: integer; 
begin 
  for x := 0 to 1 do 
    if indktn <> dblNone then lbl[x].top := Schieber[0].top + 14 else 
      lbl[x].top := height; 
end; 
 
procedure TDblSlider.setzeiger(b: boolean); 
begin 
  if b = zeiger then exit; 
  zeiger := b; 
  height := hoehe + skala * ord(zeiger) + anzeige * ord(indktn <> dblNone); 
  malzeiger; 
  repaint; 
end; 
 
procedure TDblSlider.malzeiger; 
var x, y: integer; 
begin 
  trsp := Color; 
  for x := 0 to 1 do 
    with Schieber[x].picture, bitmap, canvas do begin 
      brush.color := color; 
      fillrect(rect(0, 0, schieberbreite, 3)); 
      pen.color := color * ord(not zeiger); 
      for y := 0 to 2 do begin 
        if x = 0 then begin 
          moveto(schieberbreite - 3 + y, 2 - y); 
          lineto(schieberbreite - 3 + y, 3); 
        end else begin 
          moveto(y, y); 
          lineto(y, 3); 
        end; 
      end; 
    end; 
end; 
 
procedure TDblSlider.setzen(img: TImage); 
begin 
  img.setbounds(links, img.top, img.width, img.height); 
end; 
 
procedure TDblSlider.testen; 
begin 
  if poslinks < mini then poslinks := mini else 
    if poslinks > maxi then poslinks := maxi; 
  if posrechts < mini then posrechts := mini else 
    if posrechts > maxi then posrechts := maxi; 
end; 
 
procedure TDblSlider.rechnefreq; 
var i: single; 
begin 
  tw; 
  if f = 0 then abst := 0 else begin 
    i := (maxi - mini) / f; 
    if i < 1 then abst := 0 else 
      abst := (rts - lks) / i; 
  end; 
end; 
 
procedure TDblSlider.beidesetzen; 
begin 
  makerechts; 
  setzen(Schieber[1]); 
  makelinks; 
  setzen(Schieber[0]); 
end; 
 
procedure TDblSlider.rfbs; 
begin 
  rechnefreq; 
  beidesetzen; 
end; 
 
procedure TDblSlider.Resize; 
var h: integer; 
begin 
  inherited; 
  h := hoehe + skala * ord(zeiger) + anzeige * ord(indktn <> dblNone); 
  if width < breite then width := breite; 
  if height <> h then height := h; 
  linksrechts; 
  lblrechts; 
  rfbs; 
  repaint; 
  if einmal then feuern; 
end; 
 
procedure TDblSlider.paint; 
var x: integer; 
  d: single; 
begin 
  caption := ''; 
  for x := 0 to 1 do 
    Schieber[x].top := (height - schieberhoehe - ord(indktn <> dblNone) * 
      anzeige + ord(zeiger) * (skala + 2)) div 2 - 1; 
  inherited; 
  lbltop; 
  if trsp <> color then malzeiger; 
  with canvas do begin 
    pen.color := clBlack; 
    if zeiger then begin 
      moveto(lks, 5); 
      lineto(lks, 13); 
      moveto(rts, 5); 
      lineto(rts, 13); 
      if (abst > 0) then begin 
        d := lks + abst; 
        while d < rts do begin 
          x := round(d); 
          moveto(x, 7); 
          lineto(x, 13); 
          d := d + abst; 
        end; 
      end; 
    end; 
    brush.color := clsilver; 
    rectangle(pred(rand), Schieber[0].top + 4, width - pred(rand), 
      Schieber[0].top + 12); 
    brush.color := clWhite; 
    fillrect(rect(rand, Schieber[0].top + 5, width - rand, 
      Schieber[0].top + 7)); 
    brush.color := clgray; 
    fillrect(rect(rand, Schieber[0].top + 9, width - rand, 
      Schieber[0].top + 11)); 
  end; 
end; 
 
procedure TDblSlider.festlegen(img: Timage); 
begin 
  getcursorpos(p); 
  diffw := p.x - img.left; 
  diffs := p.y - img.top; 
  isdown := true; 
end; 
 
procedure TDblSlider.positionieren(img: TImage); 
begin 
  if img = Schieber[0] then begin 
    if links < rand then links := rand else 
      if pred(links) > Schieber[1].left - schieberbreite 
        then links := Schieber[1].left - schieberbreite + 1; 
  end else begin 
    if succ(links) < Schieber[0].left + schieberbreite then 
      links := Schieber[0].left + schieberbreite - 1 else 
      if links + img.width > width - rand then 
        links := width - rand - img.width; 
  end; 
  setzen(img); 
end; 
 
procedure TDblSlider.rechnen(img: TImage); 
begin 
  if img = Schieber[0] then 
    poslinks := Round(mini + (links - rand) * (maxi - mini) / (width - pred(2 * 
      (rand + schieberbreite)))) 
  else 
    posrechts := Round(mini + (links - rand - schieberbreite + 1) * 
      (maxi - mini) / (width - pred(2 * (rand + schieberbreite)))); 
end; 
 
procedure TDblSlider.verschieben(img: TImage); 
begin 
  getcursorpos(p); 
  links := p.x - diffw; 
  positionieren(img); 
  rechnen(img); 
  feuern; 
end; 
 
procedure TDblSlider.zahlzeigen(Sender: TImage); 
begin 
  if sender = Schieber[0] then 
    tcl.caption := #32#32 + inttostr(poslinks) + #32#32 else 
    tcl.caption := #32#32 + inttostr(posrechts) + #32#32; 
  tcl.left := (width - tcl.width) div 2; 
  if zeiger then 
    tcl.top := 2 else tcl.top := lbl[0].top; 
end; 
 
procedure TDblSlider.XMouseDown(Sender: TObject; Button: TMouseButton; 
  Shift: TShiftState; X, Y: Integer); 
begin 
  festlegen(Timage(sender)); 
  if nhint then zahlzeigen(Timage(sender)); 
  if assigned(FMouseDown) then 
    FMouseDown(self, TLftRght(ord(sender = Schieber[1])), poslinks, posrechts); 
end; 
 
procedure TDblSlider.posit1; 
begin 
  makelinks; 
  positionieren(Schieber[0]); 
end; 
 
procedure TDblSlider.posit2; 
begin 
  makerechts; 
  positionieren(Schieber[1]); 
end; 
 
procedure TDblSlider.XMouseUp(Sender: TObject; Button: TMouseButton; 
  Shift: TShiftState; X, Y: Integer); 
begin 
  isdown := false; 
  tcl.left := -maxint; 
  if sender = Schieber[0] then posit1 
  else posit2; 
  if assigned(FMouseUp) then 
    FMouseUp(self, TLftRght(ord(sender = Schieber[1])), poslinks, posrechts); 
end; 
 
procedure TDblSlider.XMouseMove(Sender: TObject; Shift: TShiftState; 
  X, Y: Integer); 
begin 
  if not isdown then exit; 
  verschieben(TImage(sender)); 
  if nhint then zahlzeigen(Timage(sender)); 
end; 
 
procedure TDblSlider.makelinks; 
begin 
  links := round((poslinks - mini) * (width - pred(2 * 
    (rand + schieberbreite))) / (maxi - mini) + rand); 
end; 
 
procedure TDblSlider.makerechts; 
begin 
  links := round((posrechts - mini) * (width - pred(2 * (rand + 
    schieberbreite))) / (maxi - mini) + rand + schieberbreite - 1); 
end; 
 
procedure TDblSlider.SetPosR(i: integer); 
begin 
  posrechts := i; 
  testen; 
  if posrechts < poslinks then posrechts := poslinks; 
  werte; 
  posit2; 
  feuern; 
  rOK := true; 
end; 
 
procedure TDblSlider.SetMin(i: integer); 
begin 
  mini := i; 
  testen; 
  if mOK then 
    if maxi <= mini then maxi := mini + 1; 
  rfbs; 
  repaint; 
  if mOK then feuern; 
end; 
 
procedure TDblSlider.SetPosL(i: integer); 
begin 
  poslinks := i; 
  testen; 
  if rOK then 
    if poslinks > posrechts then poslinks := posrechts; 
  werte; 
  posit1; 
  if rOK then feuern; 
end; 
 
procedure TDblSlider.SetMax(i: integer); 
begin 
  maxi := i; 
  if mini >= maxi then mini := maxi - 1; 
  linksrechts; 
  rfbs; 
  repaint; 
  feuern; 
  mOK := true; 
end; 
 
procedure TDblSlider.setbevel(bv: TBvl); 
begin 
  if bv = art then exit; 
  art := bv; 
  BevelOuter := TBevelCut(ord(art)); 
end; 
 
procedure TDblSlider.SetAbst(i: integer); 
begin 
  f := abs(i); 
  rechnefreq; 
  repaint; 
end; 
 
procedure TDblSlider.setnhint(b: boolean); 
begin 
  if (b = nhint) or (indktn = dblPos1Pos2) then exit; 
  nhint := b; 
  mhint := b; 
end; 
 
procedure TDblSlider.setind(i: TInd); 
begin 
  if i = indktn then exit; 
  if i = dblPos1Pos2 then nhint := false 
  else nhint := mhint; 
  indktn := i; 
  height := hoehe + skala * ord(zeiger) + anzeige * ord(i <> dblNone); 
  werte; 
end; 
 
procedure Register; 
begin 
  RegisterComponents('DBR', [TDblSlider]); 
end; 
 
end.


{ Erläuterung der Eigenschaften:

Bevel
Ist verantwortlich, ob die Komponente flach, erhaben oder versunken dargestellt wird

Max
Maximaler Wert des Sliders
(rechts)

Min
Minimaler Wert des Sliders
(links)

Frequency
Skalen-Einteilung des gesamten Bereiches
(von Min bis Max)

Indicator
Bestimmt, ob und welche Werte angezeigt werden
(Bild 3 bis Bild 5)

Scale
Schaltet die Skala ein/aus
(vergleiche Bild 1 mit Bild 2)

PositionDsp
Legt fest, ob die aktuelle Position des aktuellen Schiebers bei dessen
Betätigung angezeigt wird
(z.B. bei Bild 5 oben Mitte)

Position1
Gibt die Position des linken Schiebers zurück

Position2
Gibt die Position des rechten Schiebers zurück

OnSldMouseDown
Wird ausgelöst wenn die Maus auf einem Schieber gedrückt wird

OnSldMouseUp
Wird ausgelöst wenn die Maus auf einem Schieber losgelassen wird

OnPosChange
Wird ausgelöst, wenn ein Schieber seine Position ändert
 

//--------------- Ein paar Aufruf-Beispiele ------------------------------- 
 
procedure TForm1.Button2Click(Sender: TObject); 
begin 
  DblSlider1.Indicator := dblPos1Pos2; 
end; 

//-------------------------------------------------------------------------  

procedure TForm1.Button3Click(Sender: TObject); 
begin 
  DblSlider1.scale := not DblSlider1.scale; 
end; 

//-------------------------------------------------------------------------  

procedure TForm1.DblSlider1PosChange(Sender: TObject; Min, BandLinks, Pos1, 
  BandMitte, Pos2, BandRechts, Max: Integer); 
begin 
  label1.caption := inttostr(Min); 
  label2.caption := inttostr(BandLinks); 
  label3.caption := inttostr(Pos1); 
  label4.caption := inttostr(BandMitte); 
  label5.caption := inttostr(Pos2); 
  label6.caption := inttostr(BandRechts); 
  label7.caption := inttostr(Max); 
end; 

//-------------------------------------------------------------------------  

var 
  merklinks, merkrechts: integer; 
 
procedure TForm1.DblSlider1SldMouseDown(Sender: TObject; Wich: TLftRght; Pos1, 
  Pos2: Integer); 
begin 
  if wich = dblLeft then merklinks := Pos1 
  else merkrechts := Pos2; 
end; 
 
procedure TForm1.DblSlider1SldMouseUp(Sender: TObject; Wich: TLftRght; Pos1, 
  Pos2: Integer); 
var 
  i: integer; 
  s, z: string; 
begin 
  if wich = dblLeft then begin 
    i := abs(Pos1 - merklinks); 
    if i = 1 then z := '' else z := 'en'; 
    if Pos1 > merklinks then s := 'rechts' 
    else s := 'links'; 
    showmessage('Der linke Schieber wurde um ' + 
      inttostr(i) + ' Position' + z + ' nach ' + s + ' verschoben.'); 
  end else begin 
    i := abs(Pos2 - merkrechts); 
    if i = 1 then z := '' else z := 'en'; 
    if Pos2 > merkrechts then s := 'rechts' 
    else s := 'links'; 
    showmessage('Der rechte Schieber wurde um ' + 
      inttostr(i) + ' Position' + z + ' nach ' + s + ' verschoben.'); 
  end; 
end; 

//-------------------------------------------------------------------------  

procedure TForm1.Button1Click(Sender: TObject); 
begin 
  with DblSlider1 do 
    Frequency := (Max - Min) div 2; 
end; 

//-------------------------------------------------------------------------

}


 

Zugriffe seit 6.9.2001 auf Delphi-Ecke