Below there is a code of a TBitBtn descendant with two additional functionalities: 1. Its caption can be multiline (see the Lines property) 2. Another controls may be placed on it if the AcceptControls property is set to True (sometimes it is useful to place a TCheckBox or a TEdit on a button). Remarks: only TWinControl descendants work well when placed on the button. If you want another control (like TImage for instance), first place a TPanel and then, on the panel you can place whatever you want. Only cliks in the button area not covered by another controls trigger the button's OnClick event. 1 unit ZLBitBtn; 2 3 interface 4 5 uses 6 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, 7 Buttons, StdCtrls; 8 9 type 10 TZLBitBtn = class(TBitBtn) 11 private 12 FAcceptControls: boolean; 13 FLines: TStringList; 14 procedure SetAcceptControls(const Value: boolean); 15 procedure SetLines(const Value: TStrings); 16 function GetLines: TStrings; 17 protected 18 procedure LinesChanged(Sender: TObject); 19 procedure CreateParams(var Params: TCreateParams); override; 20 procedure WMSetText(var m: TMessage); message WM_SETTEXT; 21 public 22 constructor Create(AOwner: TComponent); override; 23 destructor Destroy; override; 24 published 25 property AcceptControls: boolean read FAcceptControls write SetAcceptControls; 26 property Lines: TStrings read GetLines write SetLines; 27 end; 28 29 procedure register; 30 31 implementation 32 33 procedure register; 34 begin 35 RegisterComponents('Samples', [TZLBitBtn]); 36 end; 37 38 {TZlBitBtn} 39 constructor TZlBitBtn.Create(AOwner: TComponent); 40 begin 41 inherited Create(AOwner); 42 FLines:=TStringList.Create; 43 FLines.OnChange:=LinesChanged; 44 if FAcceptControls then 45 ControlStyle:=ControlStyle + [csAcceptsControls]; 46 end; 47 48 procedure TZLBitBtn.CreateParams(var Params: TCreateParams); 49 begin 50 inherited CreateParams(Params); 51 Params.Style:=Params.Style or BS_MULTILINE; 52 end; 53 54 destructor TZLBitBtn.Destroy; 55 begin 56 FLines.Free; 57 inherited Destroy; 58 end; 59 60 function TZLBitBtn.GetLines: TStrings; 61 begin 62 Result:=FLines; 63 end; 64 65 procedure TZLBitBtn.LinesChanged(Sender: TObject); 66 begin 67 Caption:=Lines.Text; 68 end; 69 70 procedure TZLBitBtn.SetAcceptControls(const Value: boolean); 71 begin 72 FAcceptControls := Value; 73 if FAcceptControls then 74 ControlStyle:=ControlStyle + [csAcceptsControls] 75 else 76 ControlStyle:=ControlStyle - [csAcceptsControls]; 77 end; 78 79 procedure TZLBitBtn.SetLines(const Value: TStrings); 80 begin 81 FLines.Assign(Value); 82 end; 83 84 procedure TZLBitBtn.WMSetText(var m: TMessage); 85 var 86 OldCaption: string; 87 begin 88 OldCaption:=Caption; 89 inherited; 90 {If caption has been changed, reflect changes in Lines also} 91 if caption<>OldCaption then 92 Lines.Text:=caption; 93 end; 94 95 end.