TBrush

From Lazarus wiki
Jump to navigationJump to search

Template:TBrush

Along with TPen and TFont, TBrush belongs to the most fundamental properties of TCanvas and defines how a geometric shape is filled.

Properties

  • Color: specifies the basic color (type TColor) used to fill the shape
  • Style: an enumeration of type TBrushStyle which defines the pattern used for filling
    • bsClear: no filling at all, Color is ignored.
    • bsSolid: uniform fill of the shape with the Color specified
    • The following styles define hatch patterns which are drawn in the Color specified. By default the background between the hatch lines is left empty. In Windows, gtk2 and qt5, it can be filled after calling SetBkColor(Canvas.Handle, AColor) if background mode has been set to OPAQUE: SetBkMode(Canvas.Handle, OPAQUE) which is the default, but can be reverted by calling with the argument TRANSPARENT instead of OPAQUE. Both functions require the units LCLIntf and LCLType in the uses clause. In other widgetsets the background has to be drawn twice, with fsSolid at first. Note that an alpha-channel for transparency seems to be ignored.
      • bsHorizontal, bsVertical, bsFDiagonal, bsBDiagonal define a single-line hatch pattern.
      • bsCross and bsDiagCross define a crossed pattern.
    • bsImage and bsPattern tile the shape with the image set to the Bitmap property of the Brush.
  • Bitmap defines the image which fills the shape by tiling if Style is bsImage. Any instance of a class descending from TCustomBitmap can be used here (TBitmap, TJpegImage, TPortableNetworkgraphic, etc). But note that TCanvas.Bitmap is not created and destroyed by the Canvas, it is your responsibility to take care of this. There are also Image (type TFPCustomImage) and Pattern (type TBrushPattern) properties which seem to have a similar purpose, but they are inherited from ancestor TFPCustomBrush and are ignored by TCanvas. Using a bitmap for filling the shape does not work on all widgetsets; at the time of this writing it was tested to work on win32/64, qt5 and cocoa.

These properties are applied in all subsequent drawing commands.

Above description is valid for Windows. Several restrictions may apply for other widgetsets.

Sample code

tbrush style bk.png

The following project draws ten rectangles on the canvas of a TForm, fills them with each style and labels them with the appropriate style name. The result is shown in the image above.

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormPaint(Sender: TObject);
  private
    FPattern: TCustomBitmap;
  public
  end;

uses
  ...,
  LCLIntf, LCLType,  // for SetBkColor, OPAQUE and TRANSPARENT 
  Types,             // for OffsetRect
  TypInfo;           // for GetEnumName

procedure TForm1.FormCreate(Sender: TObject);
begin
  Width := 550;
  Height := 290;

  FPattern := TPortableNetworkGraphic.Create;
  FPattern.LoadFromFile('C:\Lazarus\images\debugger\debugger.png');  // path to the image used for filling
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FPattern.Free;
end;

procedure TForm1.FormPaint(Sender: TObject);
var
  R: TRect;
  bs: TBrushStyle;
  styleName: String;
  x, y, h: Integer;
begin
  R := Rect(8, 8, 108, 108);
  h := Canvas.TextHeight('Tg');

  // Set fill color
  Canvas.Brush.Color := clRed;

  // Set border color
  Canvas.Pen.Color := clBlack;

  // Iterate over all available brush styles
  for bs in TBrushStyle do
  begin
    // Set background color
    SetBkMode(Canvas.Handle, OPAQUE);
    SetBkColor(Canvas.Handle, clYellow); 
    // Set brush style
    Canvas.Brush.Style := bs;
    if (bs = bsImage) or (bs =bsPattern) then
      Canvas.Brush.Bitmap := FPattern
    else
      Canvas.Brush.Bitmap := nil;
    // Fill a rectangle with the selected brush
    Canvas.Rectangle(R);
    // Get name of brush style and draw it below the rectangle
    styleName := GetEnumName(TypeInfo(TBrushStyle), ord(bs));
    x := (R.Left + R.Right - Canvas.TextWidth(styleName)) div 2;
    y := R.Bottom + 8;
    // No text background
    SetBkMode(Canvas.Handle, TRANSPARENT);    // or: Canvas.Brush.Style := bsClear; 
    // Draw the brush name
    Canvas.TextOut(x, y, styleName);
    // Position the rectangle for next brush
    if ord(bs) = ord(High(bs)) div 2 then
      OffsetRect(R, -R.Left + 8, R.Height + 20 + h)
    else
      OffsetRect(R, R.Width + 8, 0);
  end;
end;