home *** CD-ROM | disk | FTP | other *** search
/ Chip 1997 April / Chip_1997-04_cd.bin / prezent / cb / data.z / EXTCTRLS.PAS < prev    next >
Pascal/Delphi Source File  |  1997-01-16  |  53KB  |  2,045 lines

  1.  
  2. {*******************************************************}
  3. {                                                       }
  4. {       Delphi Visual Component Library                 }
  5. {                                                       }
  6. {       Copyright (c) 1995,96 Borland International     }
  7. {                                                       }
  8. {*******************************************************}
  9.  
  10. unit ExtCtrls;
  11.  
  12. {$S-,W-,R-}
  13. {$C PRELOAD}
  14.  
  15. interface
  16.  
  17. uses Messages, Windows, SysUtils, Classes, Controls, Forms, Menus, Graphics,
  18.   StdCtrls;
  19.  
  20. type
  21.  
  22.   TShapeType = (stRectangle, stSquare, stRoundRect, stRoundSquare,
  23.     stEllipse, stCircle);
  24.  
  25.   TShape = class(TGraphicControl)
  26.   private
  27.     FShape: TShapeType;
  28.     FReserved: Byte;
  29.     FPen: TPen;
  30.     FBrush: TBrush;
  31.     procedure SetBrush(Value: TBrush);
  32.     procedure SetPen(Value: TPen);
  33.     procedure SetShape(Value: TShapeType);
  34.   protected
  35.     procedure Paint; override;
  36.   public
  37.     constructor Create(AOwner: TComponent); override;
  38.     destructor Destroy; override;
  39.   published
  40.     procedure StyleChanged(Sender: TObject);
  41.     property Brush: TBrush read FBrush write SetBrush;
  42.     property DragCursor;
  43.     property DragMode;
  44.     property Enabled;
  45.     property ParentShowHint;
  46.     property Pen: TPen read FPen write SetPen;
  47.     property Shape: TShapeType read FShape write SetShape default stRectangle;
  48.     property ShowHint;
  49.     property Visible;
  50.     property OnDragDrop;
  51.     property OnDragOver;
  52.     property OnEndDrag;
  53.     property OnMouseDown;
  54.     property OnMouseMove;
  55.     property OnMouseUp;
  56.     property OnStartDrag;
  57.   end;
  58.  
  59.   TPaintBox = class(TGraphicControl)
  60.   private
  61.     FOnPaint: TNotifyEvent;
  62.   protected
  63.     procedure Paint; override;
  64.   public
  65.     constructor Create(AOwner: TComponent); override;
  66.     property Canvas;
  67.   published
  68.     property Align;
  69.     property Color;
  70.     property DragCursor;
  71.     property DragMode;
  72.     property Enabled;
  73.     property Font;
  74.     property ParentColor;
  75.     property ParentFont;
  76.     property ParentShowHint;
  77.     property PopupMenu;
  78.     property ShowHint;
  79.     property Visible;
  80.     property OnClick;
  81.     property OnDblClick;
  82.     property OnDragDrop;
  83.     property OnDragOver;
  84.     property OnEndDrag;
  85.     property OnMouseDown;
  86.     property OnMouseMove;
  87.     property OnMouseUp;
  88.     property OnPaint: TNotifyEvent read FOnPaint write FOnPaint;
  89.     property OnStartDrag;
  90.   end;
  91.  
  92.   TImage = class(TGraphicControl)
  93.   private
  94.     FPicture: TPicture;
  95.     FAutoSize: Boolean;
  96.     FStretch: Boolean;
  97.     FCenter: Boolean;
  98.     FReserved: Byte;
  99.     function GetCanvas: TCanvas;
  100.     procedure PictureChanged(Sender: TObject);
  101.     procedure SetAutoSize(Value: Boolean);
  102.     procedure SetCenter(Value: Boolean);
  103.     procedure SetPicture(Value: TPicture);
  104.     procedure SetStretch(Value: Boolean);
  105.   protected
  106.     function GetPalette: HPALETTE; override;
  107.     procedure Paint; override;
  108.   public
  109.     constructor Create(AOwner: TComponent); override;
  110.     destructor Destroy; override;
  111.     property Canvas: TCanvas read GetCanvas;
  112.   published
  113.     property Align;
  114.     property AutoSize: Boolean read FAutoSize write SetAutoSize default False;
  115.     property Center: Boolean read FCenter write SetCenter default False;
  116.     property DragCursor;
  117.     property DragMode;
  118.     property Enabled;
  119.     property ParentShowHint;
  120.     property Picture: TPicture read FPicture write SetPicture;
  121.     property PopupMenu;
  122.     property ShowHint;
  123.     property Stretch: Boolean read FStretch write SetStretch default False;
  124.     property Visible;
  125.     property OnClick;
  126.     property OnDblClick;
  127.     property OnDragDrop;
  128.     property OnDragOver;
  129.     property OnEndDrag;
  130.     property OnMouseDown;
  131.     property OnMouseMove;
  132.     property OnMouseUp;
  133.     property OnStartDrag;
  134.   end;
  135.  
  136.   TBevelStyle = (bsLowered, bsRaised);
  137.   TBevelShape = (bsBox, bsFrame, bsTopLine, bsBottomLine, bsLeftLine,
  138.     bsRightLine);
  139.  
  140.   TBevel = class(TGraphicControl)
  141.   private
  142.     FStyle: TBevelStyle;
  143.     FShape: TBevelShape;
  144.     procedure SetStyle(Value: TBevelStyle);
  145.     procedure SetShape(Value: TBevelShape);
  146.   protected
  147.     procedure Paint; override;
  148.   public
  149.     constructor Create(AOwner: TComponent); override;
  150.   published
  151.     property Align;
  152.     property ParentShowHint;
  153.     property Shape: TBevelShape read FShape write SetShape default bsBox;
  154.     property ShowHint;
  155.     property Style: TBevelStyle read FStyle write SetStyle default bsLowered;
  156.     property Visible;
  157.   end;
  158.  
  159.   TTimer = class(TComponent)
  160.   private
  161.     FEnabled: Boolean;
  162.     FReserved: Byte;
  163.     FInterval: Cardinal;
  164.     FWindowHandle: HWND;
  165.     FOnTimer: TNotifyEvent;
  166.     procedure UpdateTimer;
  167.     procedure SetEnabled(Value: Boolean);
  168.     procedure SetInterval(Value: Cardinal);
  169.     procedure SetOnTimer(Value: TNotifyEvent);
  170.     procedure WndProc(var Msg: TMessage);
  171.   protected
  172.     procedure Timer; dynamic;
  173.   public
  174.     constructor Create(AOwner: TComponent); override;
  175.     destructor Destroy; override;
  176.   published
  177.     property Enabled: Boolean read FEnabled write SetEnabled default True;
  178.     property Interval: Cardinal read FInterval write SetInterval default 1000;
  179.     property OnTimer: TNotifyEvent read FOnTimer write SetOnTimer;
  180.   end;
  181.  
  182.   TPanelBevel = (bvNone, bvLowered, bvRaised);
  183.   TBevelWidth = 1..MaxInt;
  184.   TBorderWidth = 0..MaxInt;
  185.  
  186.   TCustomPanel = class(TCustomControl)
  187.   private
  188.     FBevelInner: TPanelBevel;
  189.     FBevelOuter: TPanelBevel;
  190.     FBevelWidth: TBevelWidth;
  191.     FBorderWidth: TBorderWidth;
  192.     FBorderStyle: TBorderStyle;
  193.     FFullRepaint: Boolean;
  194.     FLocked: Boolean;
  195.     FOnResize: TNotifyEvent;
  196.     FAlignment: TAlignment;
  197.     procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED;
  198.     procedure CMCtl3DChanged(var Message: TMessage); message CM_CTL3DCHANGED;
  199.     procedure CMIsToolControl(var Message: TMessage); message CM_ISTOOLCONTROL;
  200.     procedure WMSize(var Message: TWMSize); message WM_SIZE;
  201.     procedure SetAlignment(Value: TAlignment);
  202.     procedure SetBevelInner(Value: TPanelBevel);
  203.     procedure SetBevelOuter(Value: TPanelBevel);
  204.     procedure SetBevelWidth(Value: TBevelWidth);
  205.     procedure SetBorderWidth(Value: TBorderWidth);
  206.     procedure SetBorderStyle(Value: TBorderStyle);
  207.     procedure ReadData(Reader: TReader);
  208.   protected
  209.     procedure CreateParams(var Params: TCreateParams); override;
  210.     procedure AlignControls(AControl: TControl; var Rect: TRect); override;
  211.     procedure Paint; override;
  212.     procedure Resize; dynamic;
  213.     property Alignment: TAlignment read FAlignment write SetAlignment default taCenter;
  214.     property BevelInner: TPanelBevel read FBevelInner write SetBevelInner default bvNone;
  215.     property BevelOuter: TPanelBevel read FBevelOuter write SetBevelOuter default bvRaised;
  216.     property BevelWidth: TBevelWidth read FBevelWidth write SetBevelWidth default 1;
  217.     property BorderWidth: TBorderWidth read FBorderWidth write SetBorderWidth default 0;
  218.     property BorderStyle: TBorderStyle read FBorderStyle write SetBorderStyle default bsNone;
  219.     property Color default clBtnFace;
  220.     property FullRepaint: Boolean read FFullRepaint write FFullRepaint default True;
  221.     property Locked: Boolean read FLocked write FLocked default False;
  222.     property ParentColor default False;
  223.     property OnResize: TNotifyEvent read FOnResize write FOnResize;
  224.   public
  225.     constructor Create(AOwner: TComponent); override;
  226.   end;
  227.  
  228.   TPanel = class(TCustomPanel)
  229.   published
  230.     property Align;
  231.     property Alignment;
  232.     property BevelInner;
  233.     property BevelOuter;
  234.     property BevelWidth;
  235.     property BorderWidth;
  236.     property BorderStyle;
  237.     property DragCursor;
  238.     property DragMode;
  239.     property Enabled;
  240.     property Caption;
  241.     property Color;
  242.     property Ctl3D;
  243.     property Font;
  244.     property Locked;
  245.     property ParentColor;
  246.     property ParentCtl3D;
  247.     property ParentFont;
  248.     property ParentShowHint;
  249.     property PopupMenu;
  250.     property ShowHint;
  251.     property TabOrder;
  252.     property TabStop;
  253.     property Visible;
  254.     property OnClick;
  255.     property OnDblClick;
  256.     property OnDragDrop;
  257.     property OnDragOver;
  258.     property OnEndDrag;
  259.     property OnEnter;
  260.     property OnExit;
  261.     property OnMouseDown;
  262.     property OnMouseMove;
  263.     property OnMouseUp;
  264.     property OnResize;
  265.     property OnStartDrag;
  266.   end;
  267.  
  268.   TPage = class(TCustomControl)
  269.   private
  270.     procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST;
  271.   protected
  272.     procedure ReadState(Reader: TReader); override;
  273.     procedure Paint; override;
  274.   public
  275.     constructor Create(AOwner: TComponent); override;
  276.   published
  277.     property Caption;
  278.     property Height stored False;
  279.     property TabOrder stored False;
  280.     property Visible stored False;
  281.     property Width stored False;
  282.   end;
  283.  
  284.   TNotebook = class(TCustomControl)
  285.   private
  286.     FPageList: TList;
  287.     FAccess: TStrings;
  288.     FPageIndex: Integer;
  289.     FOldList: TStringList;
  290.     FOnPageChanged: TNotifyEvent;
  291.     procedure SetPages(Value: TStrings);
  292.     procedure SetActivePage(const Value: string);
  293.     function GetActivePage: string;
  294.     procedure SetPageIndex(Value: Integer);
  295.   protected
  296.     procedure CreateParams(var Params: TCreateParams); override;
  297.     function GetChildOwner: TComponent; override;
  298.     procedure GetChildren(Proc: TGetChildProc); override;
  299.     procedure ReadState(Reader: TReader); override;
  300.     procedure ShowControl(AControl: TControl); override;
  301.   public
  302.     constructor Create(AOwner: TComponent); override;
  303.     destructor Destroy; override;
  304.   published
  305.     property ActivePage: string read GetActivePage write SetActivePage stored False;
  306.     property Align;
  307.     property Color;
  308.     property Ctl3D;
  309.     property DragCursor;
  310.     property DragMode;
  311.     property Font;
  312.     property Enabled;
  313.     property PageIndex: Integer read FPageIndex write SetPageIndex default 0;
  314.     property Pages: TStrings read FAccess write SetPages stored False;
  315.     property ParentColor;
  316.     property ParentCtl3D;
  317.     property ParentFont;
  318.     property ParentShowHint;
  319.     property PopupMenu;
  320.     property ShowHint;
  321.     property TabOrder;
  322.     property TabStop;
  323.     property Visible;
  324.     property OnClick;
  325.     property OnDblClick;
  326.     property OnDragDrop;
  327.     property OnDragOver;
  328.     property OnEndDrag;
  329.     property OnEnter;
  330.     property OnExit;
  331.     property OnMouseDown;
  332.     property OnMouseMove;
  333.     property OnMouseUp;
  334.     property OnPageChanged: TNotifyEvent read FOnPageChanged write FOnPageChanged;
  335.     property OnStartDrag;
  336.   end;
  337.  
  338. { THeader
  339.   Purpose  - Creates sectioned visual header that allows each section to be
  340.              resized with the mouse.
  341.   Features - This is a design-interactive control.  In design mode, the
  342.              sections are named using the string-list editor.  Each section
  343.              can now be manually resized using the right mouse button the grab
  344.              the divider and drag to the new size.  Changing the section list
  345.              at design (or even run-time), will attempt to maintain the
  346.              section widths for sections that have not been changed.
  347.   Properties:
  348.     Align - Standard property.
  349.     AllowResize - If True, the control allows run-time mouse resizing of the
  350.                   sections.
  351.     BorderStyle - Turns the border on and off.
  352.     Font - Standard property.
  353.     Sections - A special string-list that contains the section text.
  354.     ParentFont - Standard property.
  355.     OnSizing - Event called for each mouse move during a section resize
  356.                operation.
  357.     OnSized - Event called once the size operation is complete.
  358.  
  359.     SectionWidth - Array property allowing run-time getting and setting of
  360.                    each section's width. }
  361.  
  362.   TSectionEvent = procedure(Sender: TObject;
  363.     ASection, AWidth: Integer) of object;
  364.  
  365.   THeader = class(TCustomControl)
  366.   private
  367.     FSections: TStrings;
  368.     FSectionCount: Integer;
  369.     FHitTest: TPoint;
  370.     FCanResize: Boolean;
  371.     FAllowResize: Boolean;
  372.     FResizeSection: Integer;
  373.     FBorderStyle: TBorderStyle;
  374.     FReserved: Byte;
  375.     FMouseOffset: Integer;
  376.     FOnSizing: TSectionEvent;
  377.     FOnSized: TSectionEvent;
  378.     procedure SetBorderStyle(Value: TBorderStyle);
  379.     procedure FreeSections;
  380.     procedure SetSections(Strings: TStrings);
  381.     function GetWidth(X: Integer): Integer;
  382.     procedure SetWidth(X: Integer; Value: Integer);
  383.     procedure WMSetCursor(var Msg: TWMSetCursor); message WM_SETCURSOR;
  384.     procedure WMNCHitTest(var Msg: TWMNCHitTest); message WM_NCHITTEST;
  385.     procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
  386.       X, Y: Integer); override;
  387.     procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  388.     procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
  389.       X, Y: Integer); override;
  390.   protected
  391.     procedure Paint; override;
  392.     procedure CreateParams(var Params: TCreateParams); override;
  393.     procedure Sizing(ASection, AWidth: Integer); dynamic;
  394.     procedure Sized(ASection, AWidth: Integer); dynamic;
  395.   public
  396.     constructor Create(AOwner: TComponent); override;
  397.     destructor Destroy; override;
  398.     property SectionWidth[X: Integer]: Integer read GetWidth write SetWidth;
  399.   published
  400.     property Align;
  401.     property AllowResize: Boolean read FAllowResize write FAllowResize default True;
  402.     property BorderStyle: TBorderStyle read FBorderStyle write SetBorderStyle default bsSingle;
  403.     property Enabled;
  404.     property Font;
  405.     property ParentFont;
  406.     property ParentShowHint;
  407.     property PopupMenu;
  408.     property Sections: TStrings read FSections write SetSections;
  409.     property ShowHint;
  410.     property TabOrder;
  411.     property TabStop;
  412.     property Visible;
  413.     property OnSizing: TSectionEvent read FOnSizing write FOnSizing;
  414.     property OnSized: TSectionEvent read FOnSized write FOnSized;
  415.   end;
  416.  
  417.   TCustomRadioGroup = class(TCustomGroupBox)
  418.   private
  419.     FButtons: TList;
  420.     FItems: TStrings;
  421.     FItemIndex: Integer;
  422.     FColumns: Integer;
  423.     FReading: Boolean;
  424.     FUpdating: Boolean;
  425.     procedure ArrangeButtons;
  426.     procedure ButtonClick(Sender: TObject);
  427.     procedure ItemsChange(Sender: TObject);
  428.     procedure SetButtonCount(Value: Integer);
  429.     procedure SetColumns(Value: Integer);
  430.     procedure SetItemIndex(Value: Integer);
  431.     procedure SetItems(Value: TStrings);
  432.     procedure UpdateButtons;
  433.     procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED;
  434.     procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;
  435.     procedure WMSize(var Message: TWMSize); message WM_SIZE;
  436.   protected
  437.     procedure ReadState(Reader: TReader); override;
  438.     function CanModify: Boolean; virtual;
  439.     procedure GetChildren(Proc: TGetChildProc); override;
  440.     property Columns: Integer read FColumns write SetColumns default 1;
  441.     property ItemIndex: Integer read FItemIndex write SetItemIndex default -1;
  442.     property Items: TStrings read FItems write SetItems;
  443.   public
  444.     constructor Create(AOwner: TComponent); override;
  445.     destructor Destroy; override;
  446.   end;
  447.  
  448.   TRadioGroup = class(TCustomRadioGroup)
  449.   published
  450.     property Align;
  451.     property Caption;
  452.     property Color;
  453.     property Columns;
  454.     property Ctl3D;
  455.     property DragCursor;
  456.     property DragMode;
  457.     property Enabled;
  458.     property Font;
  459.     property ItemIndex;
  460.     property Items;
  461.     property ParentColor;
  462.     property ParentCtl3D;
  463.     property ParentFont;
  464.     property ParentShowHint;
  465.     property PopupMenu;
  466.     property ShowHint;
  467.     property TabOrder;
  468.     property TabStop;
  469.     property Visible;
  470.     property OnClick;
  471.     property OnDragDrop;
  472.     property OnDragOver;
  473.     property OnEndDrag;
  474.     property OnEnter;
  475.     property OnExit;
  476.     property OnStartDrag;
  477.   end;
  478.  
  479. procedure Frame3D(Canvas: TCanvas; var Rect: TRect;
  480.   TopColor, BottomColor: TColor; Width: Integer);
  481.  
  482. implementation
  483.  
  484. uses Consts;
  485.  
  486. { Utility routines }
  487.  
  488. procedure Frame3D(Canvas: TCanvas; var Rect: TRect; TopColor, BottomColor: TColor;
  489.   Width: Integer);
  490.  
  491.   procedure DoRect;
  492.   var
  493.     TopRight, BottomLeft: TPoint;
  494.   begin
  495.     with Canvas, Rect do
  496.     begin
  497.       TopRight.X := Right;
  498.       TopRight.Y := Top;
  499.       BottomLeft.X := Left;
  500.       BottomLeft.Y := Bottom;
  501.       Pen.Color := TopColor;
  502.       PolyLine([BottomLeft, TopLeft, TopRight]);
  503.       Pen.Color := BottomColor;
  504.       Dec(BottomLeft.X);
  505.       PolyLine([TopRight, BottomRight, BottomLeft]);
  506.     end;
  507.   end;
  508.  
  509. begin
  510.   Canvas.Pen.Width := 1;
  511.   Dec(Rect.Bottom); Dec(Rect.Right);
  512.   while Width > 0 do
  513.   begin
  514.     Dec(Width);
  515.     DoRect;
  516.     InflateRect(Rect, -1, -1);
  517.   end;
  518.   Inc(Rect.Bottom); Inc(Rect.Right);
  519. end;
  520.  
  521. { TShape }
  522.  
  523. constructor TShape.Create(AOwner: TComponent);
  524. begin
  525.   inherited Create(AOwner);
  526.   ControlStyle := ControlStyle + [csReplicatable];
  527.   Width := 65;
  528.   Height := 65;
  529.   FPen := TPen.Create;
  530.   FPen.OnChange := StyleChanged;
  531.   FBrush := TBrush.Create;
  532.   FBrush.OnChange := StyleChanged;
  533. end;
  534.  
  535. destructor TShape.Destroy;
  536. begin
  537.   FPen.Free;
  538.   FBrush.Free;
  539.   inherited Destroy;
  540. end;
  541.  
  542. procedure TShape.Paint;
  543. var
  544.   X, Y, W, H, S: Integer;
  545. begin
  546.   with Canvas do
  547.   begin
  548.     Pen := FPen;
  549.     Brush := FBrush;
  550.     X := Pen.Width div 2;
  551.     Y := X;
  552.     W := Width - Pen.Width + 1;
  553.     H := Height - Pen.Width + 1;
  554.     if Pen.Width = 0 then
  555.     begin
  556.       Dec(W);
  557.       Dec(H);
  558.     end;
  559.     if W < H then S := W else S := H;
  560.     if FShape in [stSquare, stRoundSquare, stCircle] then
  561.     begin
  562.       Inc(X, (W - S) div 2);
  563.       Inc(Y, (H - S) div 2);
  564.       W := S;
  565.       H := S;
  566.     end;
  567.     case FShape of
  568.       stRectangle, stSquare:
  569.         Rectangle(X, Y, X + W, Y + H);
  570.       stRoundRect, stRoundSquare:
  571.         RoundRect(X, Y, X + W, Y + H, S div 4, S div 4);
  572.       stCircle, stEllipse:
  573.         Ellipse(X, Y, X + W, Y + H);
  574.     end;
  575.   end;
  576. end;
  577.  
  578. procedure TShape.StyleChanged(Sender: TObject);
  579. begin
  580.   Invalidate;
  581. end;
  582.  
  583. procedure TShape.SetBrush(Value: TBrush);
  584. begin
  585.   FBrush.Assign(Value);
  586. end;
  587.  
  588. procedure TShape.SetPen(Value: TPen);
  589. begin
  590.   FPen.Assign(Value);
  591. end;
  592.  
  593. procedure TShape.SetShape(Value: TShapeType);
  594. begin
  595.   if FShape <> Value then
  596.   begin
  597.     FShape := Value;
  598.     Invalidate;
  599.   end;
  600. end;
  601.  
  602. { TPaintBox }
  603.  
  604. constructor TPaintBox.Create(AOwner: TComponent);
  605. begin
  606.   inherited Create(AOwner);
  607.   ControlStyle := ControlStyle + [csReplicatable];
  608.   Width := 105;
  609.   Height := 105;
  610. end;
  611.  
  612. procedure TPaintBox.Paint;
  613. begin
  614.   Canvas.Font := Font;
  615.   Canvas.Brush.Color := Color;
  616.   if csDesigning in ComponentState then
  617.     with Canvas do
  618.     begin
  619.       Pen.Style := psDash;
  620.       Brush.Style := bsClear;
  621.       Rectangle(0, 0, Width, Height);
  622.     end;
  623.   if Assigned(FOnPaint) then FOnPaint(Self);
  624. end;
  625.  
  626. { TImage }
  627.  
  628. constructor TImage.Create(AOwner: TComponent);
  629. begin
  630.   inherited Create(AOwner);
  631.   ControlStyle := ControlStyle + [csReplicatable];
  632.   FPicture := TPicture.Create;
  633.   FPicture.OnChange := PictureChanged;
  634.   Height := 105;
  635.   Width := 105;
  636. end;
  637.  
  638. destructor TImage.Destroy;
  639. begin
  640.   FPicture.Free;
  641.   inherited Destroy;
  642. end;
  643.  
  644. function TImage.GetPalette: HPALETTE;
  645. begin
  646.   Result := 0;
  647.   if FPicture.Graphic is TBitmap then
  648.     Result := TBitmap(FPicture.Graphic).Palette;
  649. end;
  650.  
  651. procedure TImage.Paint;
  652. var
  653.   Dest: TRect;
  654. begin
  655.   if csDesigning in ComponentState then
  656.     with inherited Canvas do
  657.     begin
  658.       Pen.Style := psDash;
  659.       Brush.Style := bsClear;
  660.       Rectangle(0, 0, Width, Height);
  661.     end;
  662.   if Stretch then
  663.     Dest := ClientRect
  664.   else if Center then
  665.     Dest := Bounds((Width - Picture.Width) div 2, (Height - Picture.Height) div 2,
  666.       Picture.Width, Picture.Height)
  667.   else
  668.     Dest := Rect(0, 0, Picture.Width, Picture.Height);
  669.   with inherited Canvas do
  670.     StretchDraw(Dest, Picture.Graphic);
  671. end;
  672.  
  673. function TImage.GetCanvas: TCanvas;
  674. var
  675.   Bitmap: TBitmap;
  676. begin
  677.   if Picture.Graphic = nil then
  678.   begin
  679.     Bitmap := TBitmap.Create;
  680.     try
  681.       Bitmap.Width := Width;
  682.       Bitmap.Height := Height;
  683.       Picture.Graphic := Bitmap;
  684.     finally
  685.       Bitmap.Free;
  686.     end;
  687.   end;
  688.   if Picture.Graphic is TBitmap then
  689.     Result := TBitmap(Picture.Graphic).Canvas
  690.   else
  691.     raise EInvalidOperation.CreateRes(SImageCanvasNeedsBitmap);
  692. end;
  693.  
  694. procedure TImage.SetAutoSize(Value: Boolean);
  695. begin
  696.   FAutoSize := Value;
  697.   PictureChanged(Self);
  698. end;
  699.  
  700. procedure TImage.SetCenter(Value: Boolean);
  701. begin
  702.   if FCenter <> Value then
  703.   begin
  704.     FCenter := Value;
  705.     PictureChanged(Self);
  706.   end;
  707. end;
  708.  
  709. procedure TImage.SetPicture(Value: TPicture);
  710. begin
  711.   FPicture.Assign(Value);
  712. end;
  713.  
  714. procedure TImage.SetStretch(Value: Boolean);
  715. begin
  716.   if Value <> FStretch then
  717.   begin
  718.     FStretch := Value;
  719.     PictureChanged(Self);
  720.   end;
  721. end;
  722.  
  723. procedure TImage.PictureChanged(Sender: TObject);
  724. begin
  725.   if AutoSize and (Picture.Width > 0) and (Picture.Height > 0) then
  726.     SetBounds(Left, Top, Picture.Width, Picture.Height);
  727.   if (Picture.Graphic is TBitmap) and (Picture.Width >= Width) and
  728.     (Picture.Height >= Height) then
  729.     ControlStyle := ControlStyle + [csOpaque] else
  730.     ControlStyle := ControlStyle - [csOpaque];
  731.   Invalidate;
  732. end;
  733.  
  734. { TBevel }
  735.  
  736. constructor TBevel.Create(AOwner: TComponent);
  737. begin
  738.   inherited Create(AOwner);
  739.   ControlStyle := ControlStyle + [csReplicatable];
  740.   FStyle := bsLowered;
  741.   FShape := bsBox;
  742.   Width := 50;
  743.   Height := 50;
  744. end;
  745.  
  746. procedure TBevel.SetStyle(Value: TBevelStyle);
  747. begin
  748.   if Value <> FStyle then
  749.   begin
  750.     FStyle := Value;
  751.     Invalidate;
  752.   end;
  753. end;
  754.  
  755. procedure TBevel.SetShape(Value: TBevelShape);
  756. begin
  757.   if Value <> FShape then
  758.   begin
  759.     FShape := Value;
  760.     Invalidate;
  761.   end;
  762. end;
  763.  
  764. procedure TBevel.Paint;
  765. var
  766.   Color1, Color2: TColor;
  767.   Temp: TColor;
  768.  
  769.   procedure BevelRect(const R: TRect);
  770.   begin
  771.     with Canvas do
  772.     begin
  773.       Pen.Color := Color1;
  774.       PolyLine([Point(R.Left, R.Bottom), Point(R.Left, R.Top),
  775.         Point(R.Right, R.Top)]);
  776.       Pen.Color := Color2;
  777.       PolyLine([Point(R.Right, R.Top), Point(R.Right, R.Bottom),
  778.         Point(R.Left, R.Bottom)]);
  779.     end;
  780.   end;
  781.  
  782.   procedure BevelLine(C: TColor; X1, Y1, X2, Y2: Integer);
  783.   begin
  784.     with Canvas do
  785.     begin
  786.       Pen.Color := C;
  787.       MoveTo(X1, Y1);
  788.       LineTo(X2, Y2);
  789.     end;
  790.   end;
  791.  
  792. begin
  793.   with Canvas do
  794.   begin
  795.     Pen.Width := 1;
  796.  
  797.     if FStyle = bsLowered then
  798.     begin
  799.       Color1 := clBtnShadow;
  800.       Color2 := clBtnHighlight;
  801.     end
  802.     else
  803.     begin
  804.       Color1 := clBtnHighlight;
  805.       Color2 := clBtnShadow;
  806.     end;
  807.  
  808.     case FShape of
  809.       bsBox: BevelRect(Rect(0, 0, Width - 1, Height - 1));
  810.       bsFrame:
  811.         begin
  812.           Temp := Color1;
  813.           Color1 := Color2;
  814.           BevelRect(Rect(1, 1, Width - 1, Height - 1));
  815.           Color2 := Temp;
  816.           Color1 := Temp;
  817.           BevelRect(Rect(0, 0, Width - 2, Height - 2));
  818.         end;
  819.       bsTopLine:
  820.         begin
  821.           BevelLine(Color1, 0, 0, Width, 0);
  822.           BevelLine(Color2, 0, 1, Width, 1);
  823.         end;
  824.       bsBottomLine:
  825.         begin
  826.           BevelLine(Color1, 0, Height - 2, Width, Height - 2);
  827.           BevelLine(Color2, 0, Height - 1, Width, Height - 1);
  828.         end;
  829.       bsLeftLine:
  830.         begin
  831.           BevelLine(Color1, 0, 0, 0, Height);
  832.           BevelLine(Color2, 1, 0, 1, Height);
  833.         end;
  834.       bsRightLine:
  835.         begin
  836.           BevelLine(Color1, Width - 2, 0, Width - 2, Height);
  837.           BevelLine(Color2, Width - 1, 0, Width - 1, Height);
  838.         end;
  839.     end;
  840.   end;
  841. end;
  842.  
  843. { TTimer }
  844.  
  845. constructor TTimer.Create(AOwner: TComponent);
  846. begin
  847.   inherited Create(AOwner);
  848.   FEnabled := True;
  849.   FInterval := 1000;
  850.   FWindowHandle := AllocateHWnd(WndProc);
  851. end;
  852.  
  853. destructor TTimer.Destroy;
  854. begin
  855.   FEnabled := False;
  856.   UpdateTimer;
  857.   DeallocateHWnd(FWindowHandle);
  858.   inherited Destroy;
  859. end;
  860.  
  861. procedure TTimer.WndProc(var Msg: TMessage);
  862. begin
  863.   with Msg do
  864.     if Msg = WM_TIMER then
  865.       try
  866.         Timer;
  867.       except
  868.         Application.HandleException(Self);
  869.       end
  870.     else
  871.       Result := DefWindowProc(FWindowHandle, Msg, wParam, lParam);
  872. end;
  873.  
  874. procedure TTimer.UpdateTimer;
  875. begin
  876.   KillTimer(FWindowHandle, 1);
  877.   if (FInterval <> 0) and FEnabled and Assigned(FOnTimer) then
  878.     if SetTimer(FWindowHandle, 1, FInterval, nil) = 0 then
  879.       raise EOutOfResources.CreateRes(SNoTimers);
  880. end;
  881.  
  882. procedure TTimer.SetEnabled(Value: Boolean);
  883. begin
  884.   if Value <> FEnabled then
  885.   begin
  886.     FEnabled := Value;
  887.     UpdateTimer;
  888.   end;
  889. end;
  890.  
  891. procedure TTimer.SetInterval(Value: Cardinal);
  892. begin
  893.   if Value <> FInterval then
  894.   begin
  895.     FInterval := Value;
  896.     UpdateTimer;
  897.   end;
  898. end;
  899.  
  900. procedure TTimer.SetOnTimer(Value: TNotifyEvent);
  901. begin
  902.   FOnTimer := Value;
  903.   UpdateTimer;
  904. end;
  905.  
  906. procedure TTimer.Timer;
  907. begin
  908.   if Assigned(FOnTimer) then FOnTimer(Self);
  909. end;
  910.  
  911. { TCustomPanel }
  912.  
  913. constructor TCustomPanel.Create(AOwner: TComponent);
  914. begin
  915.   inherited Create(AOwner);
  916.   ControlStyle := [csAcceptsControls, csCaptureMouse, csClickEvents,
  917.     csSetCaption, csOpaque, csDoubleClicks, csReplicatable];
  918.   Width := 185;
  919.   Height := 41;
  920.   FAlignment := taCenter;
  921.   BevelOuter := bvRaised;
  922.   BevelWidth := 1;
  923.   FBorderStyle := bsNone;
  924.   Color := clBtnFace;
  925.   FFullRepaint := True;
  926. end;
  927.  
  928. procedure TCustomPanel.CreateParams(var Params: TCreateParams);
  929. const
  930.   BorderStyles: array[TBorderStyle] of Longint = (0, WS_BORDER);
  931. begin
  932.   inherited CreateParams(Params);
  933.   with Params do
  934.   begin
  935.     Style := Style or BorderStyles[FBorderStyle];
  936.     if NewStyleControls and Ctl3D and (FBorderStyle = bsSingle) then
  937.     begin
  938.       Style := Style and not WS_BORDER;
  939.       ExStyle := ExStyle or WS_EX_CLIENTEDGE;
  940.     end;
  941.   end;
  942. end;
  943.  
  944. procedure TCustomPanel.CMTextChanged(var Message: TMessage);
  945. begin
  946.   Invalidate;
  947. end;
  948.  
  949. procedure TCustomPanel.CMCtl3DChanged(var Message: TMessage);
  950. begin
  951.   if NewStyleControls and (FBorderStyle = bsSingle) then RecreateWnd;
  952.   inherited;
  953. end;
  954.  
  955. procedure TCustomPanel.CMIsToolControl(var Message: TMessage);
  956. begin
  957.   if not FLocked then Message.Result := 1;
  958. end;
  959.  
  960. procedure TCustomPanel.Resize;
  961. begin
  962.   if FullRepaint then Invalidate;
  963.   if Assigned(FOnResize) then FOnResize(Self);
  964. end;
  965.  
  966. procedure TCustomPanel.WMSize(var Message: TWMSize);
  967. begin
  968.   inherited;
  969.   if not (csLoading in ComponentState) then Resize;
  970. end;
  971.  
  972. procedure TCustomPanel.AlignControls(AControl: TControl; var Rect: TRect);
  973. var
  974.   BevelSize: Integer;
  975. begin
  976.   BevelSize := BorderWidth;
  977.   if BevelOuter <> bvNone then Inc(BevelSize, BevelWidth);
  978.   if BevelInner <> bvNone then Inc(BevelSize, BevelWidth);
  979.   InflateRect(Rect, -BevelSize, -BevelSize);
  980.   inherited AlignControls(AControl, Rect);
  981. end;
  982.  
  983. procedure TCustomPanel.ReadData(Reader: TReader);
  984. begin
  985.   ShowHint := Reader.ReadBoolean;
  986. end;
  987.  
  988. procedure TCustomPanel.Paint;
  989. var
  990.   Rect: TRect;
  991.   TopColor, BottomColor: TColor;
  992.   FontHeight: Integer;
  993. const
  994.   Alignments: array[TAlignment] of Word = (DT_LEFT, DT_RIGHT, DT_CENTER);
  995.  
  996.   procedure AdjustColors(Bevel: TPanelBevel);
  997.   begin
  998.     TopColor := clBtnHighlight;
  999.     if Bevel = bvLowered then TopColor := clBtnShadow;
  1000.     BottomColor := clBtnShadow;
  1001.     if Bevel = bvLowered then BottomColor := clBtnHighlight;
  1002.   end;
  1003.  
  1004. begin
  1005.   Rect := GetClientRect;
  1006.   if BevelOuter <> bvNone then
  1007.   begin
  1008.     AdjustColors(BevelOuter);
  1009.     Frame3D(Canvas, Rect, TopColor, BottomColor, BevelWidth);
  1010.   end;
  1011.   Frame3D(Canvas, Rect, Color, Color, BorderWidth);
  1012.   if BevelInner <> bvNone then
  1013.   begin
  1014.     AdjustColors(BevelInner);
  1015.     Frame3D(Canvas, Rect, TopColor, BottomColor, BevelWidth);
  1016.   end;
  1017.   with Canvas do
  1018.   begin
  1019.     Brush.Color := Color;
  1020.     FillRect(Rect);
  1021.     Brush.Style := bsClear;
  1022.     Font := Self.Font;
  1023.     FontHeight := TextHeight('W');
  1024.     with Rect do
  1025.     begin
  1026.       Top := ((Bottom + Top) - FontHeight) div 2;
  1027.       Bottom := Top + FontHeight;
  1028.     end;
  1029.     DrawText(Handle, PChar(Caption), -1, Rect, (DT_EXPANDTABS or
  1030.       DT_VCENTER) or Alignments[FAlignment]);
  1031.   end;
  1032. end;
  1033.  
  1034. procedure TCustomPanel.SetAlignment(Value: TAlignment);
  1035. begin
  1036.   FAlignment := Value;
  1037.   Invalidate;
  1038. end;
  1039.  
  1040. procedure TCustomPanel.SetBevelInner(Value: TPanelBevel);
  1041. begin
  1042.   FBevelInner := Value;
  1043.   Realign;
  1044.   Invalidate;
  1045. end;
  1046.  
  1047. procedure TCustomPanel.SetBevelOuter(Value: TPanelBevel);
  1048. begin
  1049.   FBevelOuter := Value;
  1050.   Realign;
  1051.   Invalidate;
  1052. end;
  1053.  
  1054. procedure TCustomPanel.SetBevelWidth(Value: TBevelWidth);
  1055. begin
  1056.   FBevelWidth := Value;
  1057.   Realign;
  1058.   Invalidate;
  1059. end;
  1060.  
  1061. procedure TCustomPanel.SetBorderWidth(Value: TBorderWidth);
  1062. begin
  1063.   FBorderWidth := Value;
  1064.   Realign;
  1065.   Invalidate;
  1066. end;
  1067.  
  1068. procedure TCustomPanel.SetBorderStyle(Value: TBorderStyle);
  1069. begin
  1070.   if FBorderStyle <> Value then
  1071.   begin
  1072.     FBorderStyle := Value;
  1073.     RecreateWnd;
  1074.   end;
  1075. end;
  1076.  
  1077. { TPageAccess }
  1078.  
  1079. type
  1080.   TPageAccess = class(TStrings)
  1081.   private
  1082.     PageList: TList;
  1083.     Notebook: TNotebook;
  1084.   protected
  1085.     function GetCount: Integer; override;
  1086.     function Get(Index: Integer): string; override;
  1087.     procedure Put(Index: Integer; const S: string); override;
  1088.     function GetObject(Index: Integer): TObject; override;
  1089.     procedure SetUpdateState(Updating: Boolean); override;
  1090.   public
  1091.     constructor Create(APageList: TList; ANotebook: TNotebook);
  1092.     procedure Clear; override;
  1093.     procedure Delete(Index: Integer); override;
  1094.     procedure Insert(Index: Integer; const S: string); override;
  1095.     procedure Move(CurIndex, NewIndex: Integer); override;
  1096.   end;
  1097.  
  1098. constructor TPageAccess.Create(APageList: TList; ANotebook: TNotebook);
  1099. begin
  1100.   inherited Create;
  1101.   PageList := APageList;
  1102.   Notebook := ANotebook;
  1103. end;
  1104.  
  1105. function TPageAccess.GetCount: Integer;
  1106. begin
  1107.   Result := PageList.Count;
  1108. end;
  1109.  
  1110. function TPageAccess.Get(Index: Integer): string;
  1111. begin
  1112.   Result := TPage(PageList[Index]).Caption;
  1113. end;
  1114.  
  1115. procedure TPageAccess.Put(Index: Integer; const S: string);
  1116. begin
  1117.   TPage(PageList[Index]).Caption := S;
  1118. end;
  1119.  
  1120. function TPageAccess.GetObject(Index: Integer): TObject;
  1121. begin
  1122.   Result := PageList[Index];
  1123. end;
  1124.  
  1125. procedure TPageAccess.SetUpdateState(Updating: Boolean);
  1126. begin
  1127.   { do nothing }
  1128. end;
  1129.  
  1130. procedure TPageAccess.Clear;
  1131. var
  1132.   I: Integer;
  1133. begin
  1134.   for I := 0 to PageList.Count - 1 do
  1135.     TPage(PageList[I]).Free;
  1136.   PageList.Clear;
  1137. end;
  1138.  
  1139. procedure TPageAccess.Delete(Index: Integer);
  1140. var
  1141.   Form: TForm;
  1142. begin
  1143.   TPage(PageList[Index]).Free;
  1144.   PageList.Delete(Index);
  1145.   NoteBook.PageIndex := 0;
  1146.  
  1147.   if csDesigning in NoteBook.ComponentState then
  1148.   begin
  1149.     Form := GetParentForm(NoteBook);
  1150.     if (Form <> nil) and (Form.Designer <> nil) then
  1151.       Form.Designer.Modified;
  1152.   end;
  1153. end;
  1154.  
  1155. procedure TPageAccess.Insert(Index: Integer; const S: string);
  1156. var
  1157.   Page: TPage;
  1158.   Form: TForm;
  1159. begin
  1160.   Page := TPage.Create(Notebook);
  1161.   with Page do
  1162.   begin
  1163.     Parent := Notebook;
  1164.     Caption := S;
  1165.   end;
  1166.   PageList.Insert(Index, Page);
  1167.  
  1168.   NoteBook.PageIndex := Index;
  1169.  
  1170.   if csDesigning in NoteBook.ComponentState then
  1171.   begin
  1172.     Form := GetParentForm(NoteBook);
  1173.     if (Form <> nil) and (Form.Designer <> nil) then
  1174.       Form.Designer.Modified;
  1175.   end;
  1176. end;
  1177.  
  1178. procedure TPageAccess.Move(CurIndex, NewIndex: Integer);
  1179. var
  1180.   AObject: TObject;
  1181. begin
  1182.   if CurIndex <> NewIndex then
  1183.   begin
  1184.     AObject := PageList[CurIndex];
  1185.     PageList[CurIndex] := PageList[NewIndex];
  1186.     PageList[NewIndex] := AObject;
  1187.   end;
  1188. end;
  1189.  
  1190. { TPage }
  1191.  
  1192. constructor TPage.Create(AOwner: TComponent);
  1193. begin
  1194.   inherited Create(AOwner);
  1195.   Visible := False;
  1196.   ControlStyle := ControlStyle + [csAcceptsControls];
  1197.   Align := alClient;
  1198. end;
  1199.  
  1200. procedure TPage.Paint;
  1201. begin
  1202.   inherited Paint;
  1203.   if csDesigning in ComponentState then
  1204.     with Canvas do
  1205.     begin
  1206.       Pen.Style := psDash;
  1207.       Brush.Style := bsClear;
  1208.       Rectangle(0, 0, Width, Height);
  1209.     end;
  1210. end;
  1211.  
  1212. procedure TPage.ReadState(Reader: TReader);
  1213. begin
  1214.   if Reader.Parent is TNotebook then
  1215.     TNotebook(Reader.Parent).FPageList.Add(Self);
  1216.   inherited ReadState(Reader);
  1217. end;
  1218.  
  1219. procedure TPage.WMNCHitTest(var Message: TWMNCHitTest);
  1220. begin
  1221.   if not (csDesigning in ComponentState) then
  1222.     Message.Result := HTTRANSPARENT
  1223.   else
  1224.     inherited;
  1225. end;
  1226.  
  1227. { TNotebook }
  1228.  
  1229. var
  1230.   Registered: Boolean = False;
  1231.  
  1232. constructor TNotebook.Create(AOwner: TComponent);
  1233. begin
  1234.   inherited Create(AOwner);
  1235.   Width := 150;
  1236.   Height := 150;
  1237.   FPageList := TList.Create;
  1238.   FAccess := TPageAccess.Create(FPageList, Self);
  1239.   FPageIndex := -1;
  1240.   FAccess.Add(LoadStr(SDefault));
  1241.   PageIndex := 0;
  1242.   Exclude(FComponentStyle, csInheritable);
  1243.   if not Registered then
  1244.   begin
  1245.     Classes.RegisterClasses([TPage]);
  1246.     Registered := True;
  1247.   end;
  1248. end;
  1249.  
  1250. destructor TNotebook.Destroy;
  1251. begin
  1252.   FAccess.Free;
  1253.   FPageList.Free;
  1254.   inherited Destroy;
  1255. end;
  1256.  
  1257. procedure TNotebook.CreateParams(var Params: TCreateParams);
  1258. begin
  1259.   inherited CreateParams(Params);
  1260.   with Params do Style := Style or WS_CLIPCHILDREN;
  1261. end;
  1262.  
  1263. function TNotebook.GetChildOwner: TComponent;
  1264. begin
  1265.   Result := Self;
  1266. end;
  1267.  
  1268. procedure TNotebook.GetChildren(Proc: TGetChildProc);
  1269. var
  1270.   I: Integer;
  1271. begin
  1272.   for I := 0 to FPageList.Count - 1 do Proc(TControl(FPageList[I]));
  1273. end;
  1274.  
  1275. procedure TNotebook.ReadState(Reader: TReader);
  1276. begin
  1277.   Pages.Clear;
  1278.   inherited ReadState(Reader);
  1279.   if (FPageIndex <> -1) and (FPageIndex >= 0) and (FPageIndex < FPageList.Count) then
  1280.     with TPage(FPageList[FPageIndex]) do
  1281.     begin
  1282.       BringToFront;
  1283.       Visible := True;
  1284.       Align := alClient;
  1285.     end
  1286.   else FPageIndex := -1;
  1287. end;
  1288.  
  1289. procedure TNotebook.ShowControl(AControl: TControl);
  1290. var
  1291.   I: Integer;
  1292. begin
  1293.   for I := 0 to FPageList.Count - 1 do
  1294.     if FPageList[I] = AControl then
  1295.     begin
  1296.       SetPageIndex(I);
  1297.       Exit;
  1298.     end;
  1299.   inherited ShowControl(AControl);
  1300. end;
  1301.  
  1302. procedure TNotebook.SetPages(Value: TStrings);
  1303. begin
  1304.   FAccess.Assign(Value);
  1305. end;
  1306.  
  1307. procedure TNotebook.SetPageIndex(Value: Integer);
  1308. var
  1309.   ParentForm: TForm;
  1310. begin
  1311.   if csLoading in ComponentState then
  1312.   begin
  1313.     FPageIndex := Value;
  1314.     Exit;
  1315.   end;
  1316.   if (Value <> FPageIndex) and (Value >= 0) and (Value < FPageList.Count) then
  1317.   begin
  1318.     ParentForm := GetParentForm(Self);
  1319.     if ParentForm <> nil then
  1320.       if ContainsControl(ParentForm.ActiveControl) then
  1321.         ParentForm.ActiveControl := Self;
  1322.     with TPage(FPageList[Value]) do
  1323.     begin
  1324.       BringToFront;
  1325.       Visible := True;
  1326.       Align := alClient;
  1327.     end;
  1328.     if (FPageIndex >= 0) and (FPageIndex < FPageList.Count) then
  1329.       TPage(FPageList[FPageIndex]).Visible := False;
  1330.     FPageIndex := Value;
  1331.     if ParentForm <> nil then
  1332.       if ParentForm.ActiveControl = Self then SelectFirst;
  1333.     if Assigned(FOnPageChanged) then
  1334.       FOnPageChanged(Self);
  1335.   end;
  1336. end;
  1337.  
  1338. procedure TNotebook.SetActivePage(const Value: string);
  1339. begin
  1340.   SetPageIndex(FAccess.IndexOf(Value));
  1341. end;
  1342.  
  1343. function TNotebook.GetActivePage: string;
  1344. begin
  1345.   Result := FAccess[FPageIndex];
  1346. end;
  1347.  
  1348. { THeaderStrings }
  1349.  
  1350. const
  1351.   DefaultSectionWidth = 75;
  1352.  
  1353. type
  1354.   PHeaderSection = ^THeaderSection;
  1355.   THeaderSection = record
  1356.     FObject: TObject;
  1357.     Width: Integer;
  1358.     Title: string;
  1359.   end;
  1360.  
  1361. type
  1362.   THeaderStrings = class(TStrings)
  1363.   private
  1364.     FHeader: THeader;
  1365.     FList: TList;
  1366.     procedure ReadData(Reader: TReader);
  1367.     procedure WriteData(Writer: TWriter);
  1368.   protected
  1369.     procedure DefineProperties(Filer: TFiler); override;
  1370.     function Get(Index: Integer): string; override;
  1371.     function GetCount: Integer; override;
  1372.     function GetObject(Index: Integer): TObject; override;
  1373.     procedure Put(Index: Integer; const S: string); override;
  1374.     procedure PutObject(Index: Integer; AObject: TObject); override;
  1375.     procedure SetUpdateState(Updating: Boolean); override;
  1376.   public
  1377.     constructor Create;
  1378.     destructor Destroy; override;
  1379.     procedure Assign(Source: TPersistent); override;
  1380.     procedure Delete(Index: Integer); override;
  1381.     procedure Insert(Index: Integer; const S: string); override;
  1382.     procedure Clear; override;
  1383.   end;
  1384.  
  1385. procedure FreeSection(Section: PHeaderSection);
  1386. begin
  1387.   if Section <> nil then Dispose(Section);
  1388. end;
  1389.  
  1390. function NewSection(const ATitle: string; AWidth: Integer; AObject: TObject): PHeaderSection;
  1391. begin
  1392.   New(Result);
  1393.   with Result^ do
  1394.   begin
  1395.     Title := ATitle;
  1396.     Width := AWidth;
  1397.     FObject := AObject;
  1398.   end;
  1399. end;
  1400.  
  1401. constructor THeaderStrings.Create;
  1402. begin
  1403.   inherited Create;
  1404.   FList := TList.Create;
  1405. end;
  1406.  
  1407. destructor THeaderStrings.Destroy;
  1408. begin
  1409.   if FList <> nil then
  1410.   begin
  1411.     Clear;
  1412.     FList.Destroy;
  1413.   end;
  1414.   inherited Destroy;
  1415. end;
  1416.  
  1417. procedure THeaderStrings.Assign(Source: TPersistent);
  1418. var
  1419.   I, J: Integer;
  1420.   Strings: TStrings;
  1421.   NewList: TList;
  1422.   Section: PHeaderSection;
  1423.   TempStr: string;
  1424.   Found: Boolean;
  1425. begin
  1426.   if Source is TStrings then
  1427.   begin
  1428.     Strings := TStrings(Source);
  1429.     BeginUpdate;
  1430.     try
  1431.       NewList := TList.Create;
  1432.       try
  1433.         { Delete any sections not in the new list }
  1434.         I := FList.Count - 1;
  1435.         Found := False;
  1436.         while I >= 0 do
  1437.         begin
  1438.           TempStr := Get(I);
  1439.           for J := 0 to Strings.Count - 1 do
  1440.           begin
  1441.             Found := CompareStr(Strings[J], TempStr) = 0;
  1442.             if Found then Break;
  1443.           end;
  1444.           if not Found then Delete(I);
  1445.           Dec(I);
  1446.         end;
  1447.  
  1448.         { Now iterate over the lists and maintain section widths of sections in
  1449.           the new list }
  1450.         I := 0;
  1451.         for J := 0 to Strings.Count - 1 do
  1452.         begin
  1453.           if (I < FList.Count) and (CompareStr(Strings[J], Get(I)) = 0) then
  1454.           begin
  1455.             Section := NewSection(Get(I), PHeaderSection(FList[I])^.Width, GetObject(I));
  1456.             Inc(I);
  1457.           end else
  1458.             Section := NewSection(Strings[J],
  1459.               FHeader.Canvas.TextWidth(Strings[J]) + 8, Strings.Objects[J]);
  1460.           NewList.Add(Section);
  1461.         end;
  1462.         Clear;
  1463.         FList.Destroy;
  1464.         FList := NewList;
  1465.         FHeader.Invalidate;
  1466.       except
  1467.         for I := 0 to NewList.Count - 1 do
  1468.           FreeSection(NewList[I]);
  1469.         NewList.Destroy;
  1470.         raise;
  1471.       end;
  1472.     finally
  1473.       EndUpdate;
  1474.     end;
  1475.     Exit;
  1476.   end;
  1477.   inherited Assign(Source);
  1478. end;
  1479.  
  1480. procedure THeaderStrings.DefineProperties(Filer: TFiler);
  1481. begin
  1482.   { This will allow the old file image read in }
  1483.   if Filer is TReader then inherited DefineProperties(Filer);
  1484.   Filer.DefineProperty('Sections', ReadData, WriteData, Count > 0);
  1485. end;
  1486.  
  1487. procedure THeaderStrings.Clear;
  1488. var
  1489.   I: Integer;
  1490. begin
  1491.   for I := 0 to FList.Count - 1 do
  1492.     FreeSection(FList[I]);
  1493.   FList.Clear;
  1494. end;
  1495.  
  1496. procedure THeaderStrings.Delete(Index: Integer);
  1497. begin
  1498.   FreeSection(FList[Index]);
  1499.   FList.Delete(Index);
  1500.   if FHeader <> nil then FHeader.Invalidate;
  1501. end;
  1502.  
  1503. function THeaderStrings.Get(Index: Integer): string;
  1504. begin
  1505.   Result := PHeaderSection(FList[Index])^.Title;
  1506. end;
  1507.  
  1508. function THeaderStrings.GetCount: Integer;
  1509. begin
  1510.   Result := FList.Count;
  1511. end;
  1512.  
  1513. function THeaderStrings.GetObject(Index: Integer): TObject;
  1514. begin
  1515.   Result := PHeaderSection(FList[Index])^.FObject;
  1516. end;
  1517.  
  1518. procedure THeaderStrings.Insert(Index: Integer; const S: string);
  1519. var
  1520.   Width: Integer;
  1521. begin
  1522.   if FHeader <> nil then
  1523.     Width := FHeader.Canvas.TextWidth(S) + 8
  1524.   else Width := DefaultSectionWidth;
  1525.   FList.Expand.Insert(Index, NewSection(S, Width, nil));
  1526.   if FHeader <> nil then FHeader.Invalidate;
  1527. end;
  1528.  
  1529. procedure THeaderStrings.Put(Index: Integer; const S: string);
  1530. var
  1531.   P: PHeaderSection;
  1532.   Width: Integer;
  1533. begin
  1534.   P := FList[Index];
  1535.   if FHeader <> nil then
  1536.     Width := FHeader.Canvas.TextWidth(S) + 8
  1537.   else Width := DefaultSectionWidth;
  1538.   FList[Index] := NewSection(S, Width, P^.FObject);
  1539.   FreeSection(P);
  1540.   if FHeader <> nil then FHeader.Invalidate;
  1541. end;
  1542.  
  1543. procedure THeaderStrings.PutObject(Index: Integer; AObject: TObject);
  1544. begin
  1545.   PHeaderSection(FList[Index])^.FObject := AObject;
  1546.   if FHeader <> nil then FHeader.Invalidate;
  1547. end;
  1548.  
  1549. procedure THeaderStrings.ReadData(Reader: TReader);
  1550. var
  1551.   Width, I: Integer;
  1552.   Str: string;
  1553. begin
  1554.   Reader.ReadListBegin;
  1555.   Clear;
  1556.   while not Reader.EndOfList do
  1557.   begin
  1558.     Str := Reader.ReadString;
  1559.     Width := DefaultSectionWidth;
  1560.     I := 1;
  1561.     if Str[1] = #0 then
  1562.     begin
  1563.       repeat
  1564.         Inc(I);
  1565.       until (I > Length(Str)) or (Str[I] = #0);
  1566.       Width := StrToIntDef(Copy(Str, 2, I - 2), DefaultSectionWidth);
  1567.       System.Delete(Str, 1, I);
  1568.     end;
  1569.     FList.Expand.Insert(FList.Count, NewSection(Str, Width, nil));
  1570.   end;
  1571.   Reader.ReadListEnd;
  1572. end;
  1573.  
  1574. procedure THeaderStrings.SetUpdateState(Updating: Boolean);
  1575. begin
  1576.   if FHeader <> nil then
  1577.   begin
  1578.     SendMessage(FHeader.Handle, WM_SETREDRAW, Ord(not Updating), 0);
  1579.     if not Updating then FHeader.Refresh;
  1580.   end;
  1581. end;
  1582.  
  1583. procedure THeaderStrings.WriteData(Writer: TWriter);
  1584. var
  1585.   I: Integer;
  1586.   HeaderSection: PHeaderSection;
  1587. begin
  1588.   Writer.WriteListBegin;
  1589.   for I := 0 to Count - 1 do
  1590.   begin
  1591.     HeaderSection := FList[I];
  1592.     with HeaderSection^ do
  1593.       Writer.WriteString(Format(#0'%d'#0'%s', [Width, Title]));
  1594.   end;
  1595.   Writer.WriteListEnd;
  1596. end;
  1597.  
  1598. { THeader }
  1599.  
  1600. constructor THeader.Create(AOwner: TComponent);
  1601. begin
  1602.   inherited Create(AOwner);
  1603.   ControlStyle := ControlStyle + [csDesignInteractive, csOpaque];
  1604.   Width := 250;
  1605.   Height := 25;
  1606.   FSections := THeaderStrings.Create;
  1607.   THeaderStrings(FSections).FHeader := Self;
  1608.   FAllowResize := True;
  1609.   FBorderStyle := bsSingle;
  1610. end;
  1611.  
  1612. destructor THeader.Destroy;
  1613. begin
  1614.   FreeSections;
  1615.   FSections.Free;
  1616.   inherited Destroy;
  1617. end;
  1618.  
  1619. procedure THeader.CreateParams(var Params: TCreateParams);
  1620. const
  1621.   BorderStyles: array[TBorderStyle] of Longint = (0, WS_BORDER);
  1622. begin
  1623.   inherited CreateParams(Params);
  1624.   Params.Style := Params.Style or BorderStyles[FBorderStyle];
  1625. end;
  1626.  
  1627. procedure THeader.Paint;
  1628. var
  1629.   I, Y, W: Integer;
  1630.   S: string;
  1631.   R: TRect;
  1632. begin
  1633.   with Canvas do
  1634.   begin
  1635.     Font := Self.Font;
  1636.     Brush.Color := clBtnFace;
  1637.     I := 0;
  1638.     Y := (ClientHeight - Canvas.TextHeight('T')) div 2;
  1639.     R := Rect(0, 0, 0, ClientHeight);
  1640.     W := 0;
  1641.     S := '';
  1642.     repeat
  1643.       if I < FSections.Count then
  1644.       begin
  1645.         with PHeaderSection(THeaderStrings(FSections).FList[I])^ do
  1646.         begin
  1647.           W := Width;
  1648.           S := Title;
  1649.         end;
  1650.         Inc(I);
  1651.       end;
  1652.       R.Left := R.Right;
  1653.       Inc(R.Right, W);
  1654.       if (ClientWidth - R.Right < 2) or (I = FSections.Count) then
  1655.         R.Right := ClientWidth;
  1656.       TextRect(Rect(R.Left + 1, R.Top + 1, R.Right - 1, R.Bottom - 1),
  1657.         R.Left + 3, Y, S);
  1658.       DrawEdge(Canvas.Handle, R, BDR_RAISEDINNER, BF_TOPLEFT);
  1659.       DrawEdge(Canvas.Handle, R, BDR_RAISEDINNER, BF_BOTTOMRight);
  1660.     until R.Right = ClientWidth;
  1661.   end;
  1662. end;
  1663.  
  1664. procedure THeader.FreeSections;
  1665. begin
  1666.   if FSections <> nil then
  1667.     FSections.Clear;
  1668. end;
  1669.  
  1670. procedure THeader.SetBorderStyle(Value: TBorderStyle);
  1671. begin
  1672.   if Value <> FBorderStyle then
  1673.   begin
  1674.     FBorderStyle := Value;
  1675.     RecreateWnd;
  1676.   end;
  1677. end;
  1678.  
  1679. procedure THeader.SetSections(Strings: TStrings);
  1680. begin
  1681.   FSections.Assign(Strings);
  1682. end;
  1683.  
  1684. function THeader.GetWidth(X: Integer): Integer;
  1685. var
  1686.   I, W: Integer;
  1687. begin
  1688.   if X = FSections.Count - 1 then
  1689.   begin
  1690.     W := 0;
  1691.     for I := 0 to X - 1 do
  1692.       Inc(W, PHeaderSection(THeaderStrings(FSections).FList[I])^.Width);
  1693.     Result := ClientWidth - W;
  1694.   end
  1695.   else if (X >= 0) and (X < FSections.Count) then
  1696.     Result := PHeaderSection(THeaderStrings(FSections).FList[X])^.Width
  1697.   else
  1698.     Result := 0;
  1699. end;
  1700.  
  1701. procedure THeader.SetWidth(X: Integer; Value: Integer);
  1702. begin
  1703.   if X < 0 then Exit;
  1704.   PHeaderSection(THeaderStrings(FSections).FList[X])^.Width := Value;
  1705.   Invalidate;
  1706. end;
  1707.  
  1708. procedure THeader.WMNCHitTest(var Msg: TWMNCHitTest);
  1709. begin
  1710.   inherited;
  1711.   FHitTest := SmallPointToPoint(Msg.Pos);
  1712. end;
  1713.  
  1714. procedure THeader.WMSetCursor(var Msg: TWMSetCursor);
  1715. var
  1716.   Cur: HCURSOR;
  1717.   I: Integer;
  1718.   X: Integer;
  1719. begin
  1720.   Cur := 0;
  1721.   FResizeSection := 0;
  1722.   FHitTest := ScreenToClient(FHitTest);
  1723.   X := 2;
  1724.   with Msg do
  1725.     if HitTest = HTCLIENT then
  1726.       for I := 0 to FSections.Count - 2 do  { don't count last section }
  1727.       begin
  1728.         Inc(X, PHeaderSection(THeaderStrings(FSections).FList[I])^.Width);
  1729.         FMouseOffset := X - (FHitTest.X + 2);
  1730.         if Abs(FMouseOffset) < 4 then
  1731.         begin
  1732.           Cur := LoadCursor(0, IDC_SIZEWE);
  1733.           FResizeSection := I;
  1734.           Break;
  1735.         end;
  1736.       end;
  1737.   FCanResize := (FAllowResize or (csDesigning in ComponentState)) and (Cur <> 0);
  1738.   if FCanResize then SetCursor(Cur)
  1739.   else inherited;
  1740. end;
  1741.  
  1742. procedure THeader.MouseDown(Button: TMouseButton; Shift: TShiftState;
  1743.   X, Y: Integer);
  1744. begin
  1745.   inherited MouseDown(Button, Shift, X, Y);
  1746.   if ((csDesigning in ComponentState) and (Button = mbRight)) or (Button = mbLeft) then
  1747.     if FCanResize then SetCapture(Handle);
  1748. end;
  1749.  
  1750. procedure THeader.MouseMove(Shift: TShiftState; X, Y: Integer);
  1751. var
  1752.   I: Integer;
  1753.   AbsPos: Integer;
  1754.   MinPos: Integer;
  1755.   MaxPos: Integer;
  1756. begin
  1757.   inherited MouseMove(Shift, X, Y);
  1758.   if (GetCapture = Handle) and FCanResize then
  1759.   begin
  1760.     { absolute position of this item }
  1761.     AbsPos := 2;
  1762.     for I := 0 to FResizeSection do
  1763.       Inc(AbsPos, PHeaderSection(THeaderStrings(FSections).FList[I])^.Width);
  1764.  
  1765.     if FResizeSection > 0 then MinPos := AbsPos -
  1766.       PHeaderSection(THeaderStrings(FSections).FList[FResizeSection])^.Width + 2
  1767.     else MinPos := 2;
  1768.     MaxPos := ClientWidth - 2;
  1769.     if X < MinPos then X := MinPos;
  1770.     if X > MaxPos then X := MaxPos;
  1771.  
  1772.     Dec(PHeaderSection(THeaderStrings(FSections).FList[FResizeSection])^.Width,
  1773.       (AbsPos - X - 2) - FMouseOffset);
  1774.     Sizing(FResizeSection,
  1775.       PHeaderSection(THeaderStrings(FSections).FList[FResizeSection])^.Width);
  1776.     Refresh;
  1777.   end;
  1778. end;
  1779.  
  1780. procedure THeader.MouseUp(Button: TMouseButton; Shift: TShiftState;
  1781.   X, Y: Integer);
  1782. begin
  1783.   if FCanResize then
  1784.   begin
  1785.     ReleaseCapture;
  1786.     Sized(FResizeSection,
  1787.       PHeaderSection(THeaderStrings(FSections).FList[FResizeSection])^.Width);
  1788.     FCanResize := False;
  1789.   end;
  1790.   inherited MouseUp(Button, Shift, X, Y);
  1791. end;
  1792.  
  1793. procedure THeader.Sizing(ASection, AWidth: Integer);
  1794. begin
  1795.   if Assigned(FOnSizing) then FOnSizing(Self, ASection, AWidth);
  1796. end;
  1797.  
  1798. procedure THeader.Sized(ASection, AWidth: Integer);
  1799. var
  1800.   Form: TForm;
  1801. begin
  1802.   if Assigned(FOnSized) then FOnSized(Self, ASection, AWidth);
  1803.   if csDesigning in ComponentState then
  1804.   begin
  1805.     Form := GetParentForm(Self);
  1806.     if Form <> nil then
  1807.       Form.Designer.Modified;
  1808.   end;
  1809. end;
  1810.  
  1811. { TGroupButton }
  1812.  
  1813. type
  1814.   TGroupButton = class(TRadioButton)
  1815.   private
  1816.     FInClick: Boolean;
  1817.     procedure CNCommand(var Message: TWMCommand); message CN_COMMAND;
  1818.   protected
  1819.     procedure ChangeScale(M, D: Integer); override;
  1820.     procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  1821.     procedure KeyPress(var Key: Char); override;
  1822.   public
  1823.     constructor Create(RadioGroup: TCustomRadioGroup);
  1824.     destructor Destroy; override;
  1825.   end;
  1826.  
  1827. constructor TGroupButton.Create(RadioGroup: TCustomRadioGroup);
  1828. begin
  1829.   inherited Create(RadioGroup);
  1830.   RadioGroup.FButtons.Add(Self);
  1831.   Visible := False;
  1832.   Enabled := RadioGroup.Enabled;
  1833.   ParentShowHint := False;
  1834.   OnClick := RadioGroup.ButtonClick;
  1835.   Parent := RadioGroup;
  1836. end;
  1837.  
  1838. destructor TGroupButton.Destroy;
  1839. begin
  1840.   TCustomRadioGroup(Owner).FButtons.Remove(Self);
  1841.   inherited Destroy;
  1842. end;
  1843.  
  1844. procedure TGroupButton.CNCommand(var Message: TWMCommand);
  1845. begin
  1846.   if not FInClick then
  1847.   begin
  1848.     FInClick := True;
  1849.     try
  1850.       if ((Message.NotifyCode = BN_CLICKED) or
  1851.         (Message.NotifyCode = BN_DOUBLECLICKED)) and
  1852.         TCustomRadioGroup(Parent).CanModify then
  1853.         inherited;
  1854.     except
  1855.       Application.HandleException(Self);
  1856.     end;
  1857.     FInClick := False;
  1858.   end;
  1859. end;
  1860.  
  1861. procedure TGroupButton.ChangeScale(M, D: Integer);
  1862. begin
  1863. end;
  1864.  
  1865. procedure TGroupButton.KeyPress(var Key: Char);
  1866. begin
  1867.   inherited KeyPress(Key);
  1868.   TCustomRadioGroup(Parent).KeyPress(Key);
  1869.   if (Key = #8) or (Key = ' ') then
  1870.   begin
  1871.     if not TCustomRadioGroup(Parent).CanModify then Key := #0;
  1872.   end;
  1873. end;
  1874.  
  1875. procedure TGroupButton.KeyDown(var Key: Word; Shift: TShiftState);
  1876. begin
  1877.   inherited KeyDown(Key, Shift);
  1878.   TCustomRadioGroup(Parent).KeyDown(Key, Shift);
  1879. end;
  1880.  
  1881. { TCustomRadioGroup }
  1882.  
  1883. constructor TCustomRadioGroup.Create(AOwner: TComponent);
  1884. begin
  1885.   inherited Create(AOwner);
  1886.   ControlStyle := [csSetCaption, csDoubleClicks];
  1887.   FButtons := TList.Create;
  1888.   FItems := TStringList.Create;
  1889.   TStringList(FItems).OnChange := ItemsChange;
  1890.   FItemIndex := -1;
  1891.   FColumns := 1;
  1892. end;
  1893.  
  1894. destructor TCustomRadioGroup.Destroy;
  1895. begin
  1896.   SetButtonCount(0);
  1897.   TStringList(FItems).OnChange := nil;
  1898.   FItems.Free;
  1899.   FButtons.Free;
  1900.   inherited Destroy;
  1901. end;
  1902.  
  1903. procedure TCustomRadioGroup.ArrangeButtons;
  1904. var
  1905.   ButtonsPerCol, ButtonWidth, ButtonHeight, TopMargin, I: Integer;
  1906.   DC: HDC;
  1907.   SaveFont: HFont;
  1908.   Metrics: TTextMetric;
  1909. begin
  1910.   if (FButtons.Count <> 0) and not FReading then
  1911.   begin
  1912.     DC := GetDC(0);
  1913.     SaveFont := SelectObject(DC, Font.Handle);
  1914.     GetTextMetrics(DC, Metrics);
  1915.     SelectObject(DC, SaveFont);
  1916.     ReleaseDC(0, DC);
  1917.     ButtonsPerCol := (FButtons.Count + FColumns - 1) div FColumns;
  1918.     ButtonWidth := (Width - 10) div FColumns;
  1919.     I := Height - Metrics.tmHeight - 5;
  1920.     ButtonHeight := I div ButtonsPerCol;
  1921.     TopMargin := Metrics.tmHeight + 1 + (I mod ButtonsPerCol) div 2;
  1922.     for I := 0 to FButtons.Count - 1 do
  1923.       with TGroupButton(FButtons[I]) do
  1924.       begin
  1925.         SetBounds((I div ButtonsPerCol) * ButtonWidth + 8,
  1926.           (I mod ButtonsPerCol) * ButtonHeight + TopMargin,
  1927.           ButtonWidth, ButtonHeight);
  1928.         Visible := True;
  1929.       end;
  1930.   end;
  1931. end;
  1932.  
  1933. procedure TCustomRadioGroup.ButtonClick(Sender: TObject);
  1934. begin
  1935.   if not FUpdating then
  1936.   begin
  1937.     FItemIndex := FButtons.IndexOf(Sender);
  1938.     Click;
  1939.   end;
  1940. end;
  1941.  
  1942. procedure TCustomRadioGroup.ItemsChange(Sender: TObject);
  1943. begin
  1944.   if not FReading then
  1945.   begin
  1946.     if FItemIndex >= FItems.Count then FItemIndex := FItems.Count - 1;
  1947.     UpdateButtons;
  1948.   end;
  1949. end;
  1950.  
  1951. procedure TCustomRadioGroup.ReadState(Reader: TReader);
  1952. begin
  1953.   FReading := True;
  1954.   inherited ReadState(Reader);
  1955.   FReading := False;
  1956.   UpdateButtons;
  1957. end;
  1958.  
  1959. procedure TCustomRadioGroup.SetButtonCount(Value: Integer);
  1960. begin
  1961.   while FButtons.Count < Value do TGroupButton.Create(Self);
  1962.   while FButtons.Count > Value do TGroupButton(FButtons.Last).Free;
  1963. end;
  1964.  
  1965. procedure TCustomRadioGroup.SetColumns(Value: Integer);
  1966. begin
  1967.   if Value < 1 then Value := 1;
  1968.   if Value > 16 then Value := 16;
  1969.   if FColumns <> Value then
  1970.   begin
  1971.     FColumns := Value;
  1972.     ArrangeButtons;
  1973.   end;
  1974. end;
  1975.  
  1976. procedure TCustomRadioGroup.SetItemIndex(Value: Integer);
  1977. begin
  1978.   if FReading then FItemIndex := Value else
  1979.   begin
  1980.     if Value < -1 then Value := -1;
  1981.     if Value >= FButtons.Count then Value := FButtons.Count - 1;
  1982.     if FItemIndex <> Value then
  1983.     begin
  1984.       if FItemIndex >= 0 then
  1985.         TGroupButton(FButtons[FItemIndex]).Checked := False;
  1986.       FItemIndex := Value;
  1987.       if FItemIndex >= 0 then
  1988.         TGroupButton(FButtons[FItemIndex]).Checked := True;
  1989.     end;
  1990.   end;
  1991. end;
  1992.  
  1993. procedure TCustomRadioGroup.SetItems(Value: TStrings);
  1994. begin
  1995.   FItems.Assign(Value);
  1996. end;
  1997.  
  1998. procedure TCustomRadioGroup.UpdateButtons;
  1999. var
  2000.   I: Integer;
  2001. begin
  2002.   SetButtonCount(FItems.Count);
  2003.   for I := 0 to FButtons.Count - 1 do
  2004.     TGroupButton(FButtons[I]).Caption := FItems[I];
  2005.   if FItemIndex >= 0 then
  2006.   begin
  2007.     FUpdating := True;
  2008.     TGroupButton(FButtons[FItemIndex]).Checked := True;
  2009.     FUpdating := False;
  2010.   end;
  2011.   ArrangeButtons;
  2012. end;
  2013.  
  2014. procedure TCustomRadioGroup.CMEnabledChanged(var Message: TMessage);
  2015. var
  2016.   I: Integer;
  2017. begin
  2018.   inherited;
  2019.   for I := 0 to FButtons.Count - 1 do
  2020.     TGroupButton(FButtons[I]).Enabled := Enabled;
  2021. end;
  2022.  
  2023. procedure TCustomRadioGroup.CMFontChanged(var Message: TMessage);
  2024. begin
  2025.   inherited;
  2026.   ArrangeButtons;
  2027. end;
  2028.  
  2029. procedure TCustomRadioGroup.WMSize(var Message: TWMSize);
  2030. begin
  2031.   inherited;
  2032.   ArrangeButtons;
  2033. end;
  2034.  
  2035. function TCustomRadioGroup.CanModify: Boolean;
  2036. begin
  2037.   Result := True;
  2038. end;
  2039.  
  2040. procedure TCustomRadioGroup.GetChildren(Proc: TGetChildProc);
  2041. begin
  2042. end;
  2043.  
  2044. end.
  2045.