// Ich habe eine Komponente für einen Button geschrieben, welcher ähnlich dem
// Speedbutton ist; zwar nicht mit allen Funtionen des Speedbuttons, dafür
// aber mit einem 2D-Rahmen.
// Bei
Flat=False verhält er sich wie ein normaler Button. Bei Flat=True wird
// sein Aussehen von den Eigenschaften
Anheben und Rahmen bestimmt. Ist
//
Anheben=True, dann bekommt er beim Darüberstreichen mit der Maus ein
// 3D-Aussehen. Verlässt die Maus den Button, senkt er sich wieder ab. Ist
//
Anheben=False und Rahmen=False, dann wird beim Kontakt mit dem Mauspfeil
// der 2D-Rahmen gezeichnet, wie auch bei
Rahmen=True. Zusätzlich gibt es die
// Eigenschaft
Color für farbige Buttons und Rahmenfarbe für farbige 2D-Rahmen.
// Mit der Eigenschaft
MausIstDrauf (nur zur Laufzeit, nur Lesen) kann man
// abfragen, ob sich der Mauspfeil gerade über dem Button befindet.
// Die Eigenschaft
ParentColorR setzt die Rahmenfarbe zurück.
// Durch negative Werte bei
Spacing und entsprechend große Werte bei Margin
// kann die Position von Glyph und Caption horizontal vertauscht und mit
//
CaptionTop und GlyphTop die entsprechenden Höhen eingestellt werden.
// z.B.:

  with RButton1 do begin
 height:=50;
 width:=100;
 margin:=70;
 spacing:=-70;
 captiontop:=25;
 glyphtop:=10;
end;
Ergibt dieses Bild:  
 

// Mit dem Wert -1 bei Margin, Spacing, CaptionTop und GlyphTop wird eine
// horizontale bzw. vertikale Zentrierung erreicht.
// Wenn
GroupIndex einen Wert ungleich 0 hat, rastet der Button ein.
// Mit
NotEnabledBild wird die Farbe des Bitmaps im Zustand not enabled
// festgelegt und mit NotEnabledSelbst wird gesteuert, ob immer ein eigenes
// Bild für diesen Zustand angezeigt wird, auch wenn im Glyph eigentlich ein
// Bild dafür vorhanden ist.
Achtung: Die transparente Farbe des Glyph darf
// nicht mit NotEnabledBild übereinstimmen, da sonst kein Bild zu sehen ist,
// wenn der Button auf disabled steht. Bei Transparent = True wird weder ein
// Glyph noch eine Beschriftung angezeigt, dafür aber immer ein Rahmen, damit
// der Button überhaupt wahrnehmbar ist.


// Getestet mit D4 unter WinME

unit RButton; 
 
interface 
 
uses 
  Windows, Buttons, sysutils, Messages, Classes, Controls, Graphics; 
 
type 
  TRButton = class(TGraphicControl) 
  private 
    farb, nec, neb: TColor; 
    r, fl, flz, rz, heb, trans, pc, dwn, dr, zwb, mrke, im, alu: boolean; 
    unten, frm, vfrm: UINT; 
    txt: string; 
    v, h, l, bv, sp, tb, links, twi, mg, oben, ctop, gtop, gri: integer; 
    welch, merk: byte; 
    anz, mbld: TNumGlyphs; 
    bild: TBitmap; 
    teil: array[0..3] of TBitmap; 
    FOnEnter, FOnLeave: TNotifyevent; 
    rec, rct: TRect; 
  protected 
    procedure immer(b: boolean); 
    procedure feststellen(pct: TBitmap); 
    procedure setgri(i: integer); 
    procedure setctop(i: integer); 
    procedure setgtop(i: integer); 
    procedure setnec(c: Tcolor); 
    procedure setneb(c: Tcolor); 
    procedure setmargin(i: integer); 
    procedure textplatz; 
    procedure setspace(s: integer); 
    procedure rechnen; 
    procedure enBild; 
    procedure bildcreate; 
    procedure setnum(b: TNumGlyphs); 
    procedure laden(pct: TBitmap); 
    procedure runter; 
    procedure rauf; 
    procedure setdown(b: boolean); 
    procedure setpc(b: boolean); 
    procedure setfarb(c: TColor); 
    procedure setenabled(value: boolean); override; 
    procedure MouseDown(Button: TMouseButton; 
      Shift: TShiftState; X, Y: Integer); override; 
    procedure MouseUp(Button: TMouseButton; 
      Shift: TShiftState; X, Y: Integer); override; 
    procedure Resize; override; 
    procedure setfl(b: boolean); 
    procedure setr(b: boolean); 
    procedure settrans(b: boolean); 
    procedure setcpt(s: string); 
    procedure MEnter(var EMsg: TMessage); message CM_MouseEnter; 
    procedure MLeave(var LMsg: TMessage); message CM_MouseLeave; 
    procedure paint; override; 
    procedure loaded; override; 
  public 
    constructor create(aowner: tcomponent); override; 
    destructor Destroy; override; 
    property MausIstDrauf: boolean read dr; 
  published 
    property OnMouseEnter: TNotifyevent read FOnEnter write FOnEnter; 
    property OnMouseLeave: TNotifyevent read FOnLeave write FOnLeave; 
    property OnMouseMove; 
    property OnMousedown; 
    property OnMouseUp; 
    property OnResize; 
    property OnClick; 
    property Font; 
    property ParentFont; 
    property Color; 
    property ParentColor; 
    property Enabled; 
    property Visible; 
    property Hint; 
    property ShowHint; 
    property ParentShowHint; 
    property Margin: integer read mg write setmargin; 
    property Spacing: integer read sp write setspace; 
    property Down: boolean read dwn write setdown; 
    property Transparent: boolean read trans write settrans; 
    property Flat: boolean read fl write setfl; 
    property Caption: string read txt write setcpt; 
    property Rahmen: boolean read r write setr; 
    property Anheben: boolean read heb write heb; 
    property RahmenFarbe: TColor read farb write setfarb; 
    property ParentColorR: boolean read pc write setpc; 
    property Glyph: TBitmap read bild write laden; 
    property NumGlyphs: TNumGlyphs read anz write setnum; 
    property CaptionTop: integer read ctop write setctop; 
    property GlyphTop: integer read gtop write setgtop; 
    property NotEnabledColor: TColor read nec write setnec; 
    property NotEnabledBild: TColor read neb write setneb; 
    property GroupIndex: integer read gri write setgri; 
    property NotEnabledSelbst: boolean read im write immer; 
    property AllowAllUp: boolean read alu write alu; 
  end; 
 
procedure Register; 
 
implementation 
 
constructor TRButton.create(aowner: tcomponent); 
var x: byte; 
begin 
  inherited create(aowner); 
  bild := TBitmap.create; 
  for x := 0 to 3 do 
    teil[x] := TBitmap.create; 
  width := 25; 
  height := 25; 
  r := true; 
  v := 4; 
  h := 5; 
  fl := true; 
  flz := true; 
  rz := true; 
  pc := true; 
  sp := -1; 
  mg := -1; 
  farb := cl3DDkShadow; 
  unten := BDR_RAISEDINNER or BDR_RAISEDOUTER; 
  ctop := -1; 
  gtop := -1; 
  nec := clbtnface; 
  vfrm := DT_VCENTER; 
  mrke := enabled; 
  neb := clBtnShadow; 
end; 
 
destructor TRButton.Destroy; 
var x: byte; 
begin 
  for x := 3 downto 0 do 
    teil[x].free; 
  bild.free; 
  inherited Destroy; 
end; 
 
procedure TRButton.setgri(i: integer); 
begin 
  if i = gri then exit; 
  gri := i; 
  if (i = 0) and dwn then down := false; 
end; 
 
procedure TRButton.MEnter(var EMsg: TMessage); 
begin 
  dr := true; 
  if fl and enabled then begin 
    flz := not heb; 
    if flz and (not r) then rz := true; 
    textplatz; 
  end; 
  paint; 
  if assigned(FOnEnter) then FOnEnter(self); 
end; 
 
procedure TRButton.MLeave(var LMsg: TMessage); 
begin 
  dr := false; 
  flz := fl; 
  rz := r; 
  textplatz; 
  paint; 
  if assigned(FOnLeave) then FOnLeave(self); 
end; 
 
procedure TRButton.setr(b: boolean); 
begin 
  if b = r then exit; 
  r := b; 
  rz := b; 
  invalidate; 
end; 
 
procedure TRButton.setcpt(s: string); 
begin 
  if s = txt then exit; 
  txt := s; 
  l := length(txt); 
  if txt = '' then twi := 0 
  else twi := canvas.textwidth(txt); 
  textplatz; 
  invalidate; 
end; 
 
procedure TRButton.setfl(b: boolean); 
begin 
  if b = fl then exit; 
  fl := b; 
  flz := fl; 
  invalidate; 
end; 
 
procedure TRButton.settrans(b: boolean); 
begin 
  if b = trans then exit; 
  trans := b; 
  zwb := dwn; 
  invalidate; 
end; 
 
procedure TRButton.runter; 
var x: integer; 
begin 
  unten := BDR_SUNKENINNER or BDR_SUNKENOUTER; 
  v := 5; 
  h := 4; 
  bv := 1; 
  welch := 2; 
  dwn := true; 
  textplatz; 
  if gri <> 0 then 
    for x := 0 to owner.componentcount - 1 do begin 
      if (self.componentindex <> x) then begin 
        if (owner.components[x] is TRButton) 
          then begin 
          if TRButton(owner.components[x]).gri = self.gri then 
            TRButton(owner.components[x]).down := false; 
        end; 
      end; 
    end; 
  if not enabled then welch := 1; 
  invalidate; 
end; 
 
procedure TRButton.MouseDown(Button: TMouseButton; 
  Shift: TShiftState; X, Y: Integer); 
begin 
  if button = mbleft then begin 
    if gri <> 0 then zwb := not zwb; 
    runter; 
  end; 
  if assigned(onmousedown) then onmousedown(self, button, shift, x, y); 
end; 
 
procedure TRButton.rauf; 
begin 
  unten := BDR_RAISEDINNER or BDR_RAISEDOUTER; 
  v := 4; 
  h := 5; 
  bv := 0; 
  welch := 0; 
  dwn := false; 
  textplatz; 
  if not enabled then welch := 1; 
  invalidate; 
end; 
 
procedure TRButton.MouseUp(Button: TMouseButton; 
  Shift: TShiftState; X, Y: Integer); 
begin 
  if button = mbleft then 
    if (not zwb) and (alu) or (gri = 0) then rauf else begin 
      welch := 3; 
      invalidate; 
    end; 
  if assigned(onmouseup) then onmouseup(self, button, shift, x, y); 
end; 
 
procedure TRButton.setdown(b: boolean); 
begin 
  if b = dwn then exit; 
  if b then begin if gri <> 0 then zwb := true; 
    runter; 
  end else begin zwb := false; 
    rauf; 
  end; 
end; 
 
procedure TRButton.setfarb(c: TColor); 
begin 
  if c = farb then exit; 
  farb := c; 
  canvas.Pen.color := farb; 
  pc := false; 
  invalidate; 
end; 
 
procedure TRButton.setpc(b: boolean); 
begin 
  if pc = b then exit; 
  pc := b; 
  if b then begin 
    farb := cl3DDkShadow; 
    canvas.pen.color := farb; 
  end; 
  invalidate; 
end; 
 
procedure TRButton.setenabled(value: boolean); 
begin 
  inherited; 
  if mrke = enabled then exit; 
  if not enabled then begin 
    welch := 1; 
    mrke := false; 
  end else begin 
    canvas.pen.color := farb; 
    mrke := true; 
    if merk = 1 then 
      if dwn then merk := 3 else merk := 0; 
    welch := merk; 
  end; 
  invalidate; 
end; 
 
procedure TRButton.setmargin(i: integer); 
begin 
  if i < -1 then i := -1; 
  if i = mg then exit; 
  mg := i; 
  textplatz; 
  invalidate; 
end; 
 
procedure TRButton.setctop(i: integer); 
begin 
  if i = ctop then exit; 
  ctop := i; 
  textplatz; 
  invalidate; 
end; 
 
procedure TRButton.setgtop(i: integer); 
begin 
  if i = gtop then exit; 
  gtop := i; 
  textplatz; 
  invalidate; 
end; 
 
procedure TRButton.setneb(c: TColor); 
begin 
  if c = neb then exit; 
  neb := c; 
  bildcreate; 
  invalidate; 
end; 
 
procedure TRButton.setnec(c: TColor); 
begin 
  if c = nec then exit; 
  nec := c; 
  if not enabled then invalidate; 
end; 
 
procedure TRButton.textplatz; 
var spcz, coben, cunten: integer; 
  procedure spac; 
  begin 
    if (mg = -1) or (tb = 0) then begin 
      if tb = 0 then links := v + bv else 
        links := bv + (width - tb - spcz - twi) div (2 + ord((sp = -1) 
          and (twi > 0))) 
    end else links := mg + bv; 
  end; 
begin 
  if (sp = -1) or (twi = 0) then begin 
    spcz := 0; 
    spac; 
    frm := DT_CENTER; 
  end else begin 
    spcz := sp; 
    spac; 
    frm := DT_LEFT; 
  end; 
  if gtop = -1 then 
    oben := bv + (height - teil[welch].height) div 2 
  else 
    oben := gtop + bv; 
  if ctop = -1 then begin 
    coben := v; 
    cunten := height - h; 
    vfrm := DT_VCENTER; 
  end else begin 
    coben := ctop + bv; 
    cunten := coben + height; 
    vfrm := DT_top; 
  end; 
  rct := rect(links + spcz + tb, coben + 1, width - h, cunten); 
end; 
 
procedure TRButton.rechnen; 
begin 
  rec := rect(0, 0, width, height); 
  textplatz; 
end; 
 
procedure TRButton.setspace(s: integer); 
begin 
  if s = sp then exit; 
  sp := s; 
  rechnen; 
  invalidate; 
end; 
 
procedure TRButton.Resize; 
begin 
  rechnen; 
  inherited; 
end; 
 
procedure TRButton.loaded; 
begin 
  inherited; 
  bildcreate; 
  zwb := dwn; 
end; 
 
procedure TRButton.enBild; 
var 
  fb: TColor; 
  x, y: integer; 
begin 
  teil[1].width := teil[0].width; 
  teil[1].height := teil[0].height; 
  fb := teil[0].canvas.pixels[0, teil[0].height - 1]; 
  for x := 0 to teil[1].width - 1 do 
    for y := 0 to teil[1].height - 1 do begin 
      if teil[0].canvas.pixels[x, y] <> fb 
        then teil[1].canvas.pixels[x, y] := neb 
      else teil[1].canvas.pixels[x, y] := fb or $20000000; 
    end; 
  teil[1].transparent := true; 
end; 
 
procedure TRButton.bildcreate; 
var y: byte; 
  procedure mach(x: byte); 
  begin 
    teil[x].height := bild.height; 
    teil[x].width := bild.width div mbld; 
    teil[x].canvas.copyrect(teil[x].canvas.cliprect, bild.canvas, 
      rect(teil[x].width * x, 0, teil[x].width * (x + 1), bild.height)); 
    teil[x].transparent := true; 
  end; 
begin 
  feststellen(bild); 
  mach(0); 
  tb := teil[0].width; 
  case anz of 
    1: begin 
        enBild; 
        for y := 2 to 3 do teil[y].assign(teil[0]); 
      end; 
    2: begin 
        if im then enBild else mach(1); 
        for y := 2 to 3 do teil[y].assign(teil[0]); 
      end; 
    3: begin 
        if im then enBild else mach(1); 
        mach(2); 
        teil[3].assign(teil[0]); 
      end; 
    4: begin 
        if im then enBild else mach(1); 
        for y := 2 to 3 do mach(y); 
      end; 
  end; 
  rechnen; 
end; 
 
procedure TRButton.immer(b: boolean); 
begin 
  if b = im then exit; 
  im := b; 
  bildcreate; 
  invalidate; 
end; 
 
procedure TRButton.feststellen(pct: TBitmap); 
begin 
  if bild.width <= bild.height then mbld := 1 
  else mbld := bild.width div bild.height; 
  if mbld > 4 then mbld := 4; 
end; 
 
procedure TRButton.laden(pct: TBitmap); 
var rc: TRect; 
begin 
  bild.assign(pct); 
  if bild.width <= bild.height then anz := 1 
  else anz := bild.width div bild.height; 
  if anz > 4 then begin 
    bild.width := (pct.width div anz) * 4; 
    anz := 4; 
    rc := rect(0, 0, bild.width, bild.height); 
    bild.canvas.copyrect(rc, pct.canvas, rc); 
  end; 
  bildcreate; 
  invalidate; 
end; 
 
procedure TRButton.setnum(b: TNumGlyphs); 
begin 
  if b = anz then exit; 
  anz := b; 
  bildcreate; 
  invalidate; 
end; 
 
procedure TRButton.paint; 
begin 
  if not mrke then begin 
    if trans then canvas.brush.style := bsclear else 
      canvas.Brush.color := nec; 
    if r then begin 
      canvas.pen.style := pssolid; 
      canvas.pen.color := neb 
    end else canvas.pen.style := psclear; 
    canvas.rectangle(0, 0, width, height); 
    if r and not fl then begin 
      if dwn then 
        canvas.pen.color := neb else 
        canvas.pen.color := clbtnhighlight; 
      canvas.moveto(1, height - 2); 
      canvas.lineto(1, 1); 
      canvas.lineto(width - 1, 1); 
    end; 
  end else begin 
    if not trans then begin 
      canvas.pen.style := psclear; 
      canvas.Brush.color := color; 
      canvas.rectangle(ord(dwn), ord(dwn), width, height); 
    end; 
    canvas.pen.style := pssolid; 
    if (r or dr or trans) then 
      canvas.Pen.color := farb 
    else canvas.pen.color := color; 
    canvas.brush.style := bsclear; 
    canvas.rectangle(0, 0, width, height); 
  end; 
  canvas.font := font; 
  if not trans then begin 
    canvas.draw(links, oben + 1, teil[welch]); 
    if not enabled then canvas.Font.color := neb; 
    drawtext(canvas.handle, pchar(txt), l, rct, DT_SINGLELINE or vfrm or frm); 
  end; 
  if not flz then begin 
    if mrke then 
      drawedge(canvas.handle, rec, unten, BF_RECT); 
  end 
  else begin 
    if mrke and rz and dwn then begin 
      canvas.pen.color := cl3DDkShadow; 
      canvas.moveto(1, height - 2); 
      canvas.lineto(1, 1); 
      canvas.lineto(width - 1, 1); 
    end; 
  end; 
end; 
 
procedure Register; 
begin 
  RegisterComponents('DBR', [TRButton]); 
end; 
 
end.



Zugriffe seit 6.9.2001 auf Delphi-Ecke