Lance Leonard'; $attrinfo = "Various sources"; $audience = "1"; $versions = "Applies to: All versions"; $postdate = "25 March 2003"; $pagearea = 3; $navlinks = 'Delphi:'; $metakeys = "borland delphi, delphi, button, word-wrap, word wrap, word, wrap, multi-line, multi, line, caption, component, vcl, create, class completion, class"; $metadesc = "Shows how to create a tButton descendant that supports multi-line captions."; ?>

Question: How can I create buttons that support multi-line captions (e.g. ones with word wrap properties)?

There are several different ways you can do this. In our experience, the best--and easiest--is to create a TButton descendant that adds a WordWrap property to support multi-line captions. The following walkthrough demonstrates this by:

Note: This tutorial was written using Delphi 6; if you're using a different version, you may need to change certain values to work within your environment.

  1. From the Delphi main menu, choose File | New | Other.

  2. When the New Items dialog appears, select Component and then choose OK. This displays the New Component dialog.

  3. Enter the following values:

    Setting Value
    Ancestor Type TButton [StdCtrls]
    Class Name TWrapButton
    Palette Page Standard
    Unit File name C:\Program Files\Borland\Delphi6\Lib\WrapBtn.pas

    Verify your values and then choose OK.

  4. Modify the declaration of TWrapButton as follows:

    type
      TWrapButton = class(TButton)
      private
        { Private declarations }
        FWordWrap : Boolean;
        procedure SetWordWrap(AValue: Boolean);
      protected
        { Protected declarations }
        procedure CreateParams(var Params: TCreateParams); override;
      public
        { Public declarations }
        constructor Create(AOwner: TComponent); override;
      published
        { Published declarations }
        property WordWrap: Boolean read fWordWrap write SetWordWrap default FALSE;
      end;

    This adds a WordWrap property to your button, as well as the tools for manage the property's values and effects. It also overrides two existing procedures in the ancestor class.

  5. Now, press Shift+Ctrl+C to trigger Delphi's Class Completion feature; this creates skeletal procedures for your class by adding three procedures to the Implementation section.

  6. Next, modify your procedures as follows (changes are in bold):

    constructor TWrapButton.Create(AOwner: TComponent);
    begin
      inherited;
      if FWordWrap <> TRUE then
         FWordWrap := TRUE;
    end;
    
    procedure TWrapButton.CreateParams(var Params: TCreateParams);
    begin
      inherited;
      if WordWrap then
        Params.Style := Params.Style or BS_MULTILINE
      else
        Params.Style := Params.Style and not BS_MULTILINE;
    end;
    
    
    procedure TWrapButton.SetWordWrap(AValue: Boolean);
    begin
      if fWordWrap <> AValue then
      begin
        fWordWrap := AValue;
        recreateWnd;
      end;
    end;
  7. Next, install the component by choosing Component | Install Component. This displays the Install Component dialog.

  8. Choose the Into New Package tab and then enter the following values:

    Setting Value
    Package File Name myvcls.dpk
    Package Description My Custom Delphi Components

    Verify your values and then choose OK.

  9. Delphi now asks for permission to build, then install your component. Choose Yes. You should receive an information prompt telling you that your component has been built and installed into the component palette. You can verify this by selecting the Standard tab on the palette; you should see another button icon on the very end of the palette. If you point to it with the mouse, the tooltip shows it's the component you just created.

Congratulations, you've just created a new component with little to no idea of the original class (though the source is provided with certain versions of Delphi). This flexibility is one of the reasons why Delphi is so popular.