Skip to main content

Creating a Custom Hot Zone Style

  • 5 minutes to read

A Splitter control (a TcxCustomSplitter descendant) provides a hot zone facility. Hot zones are control elements that can be clicked to collapse the splitter (set its bound control to the minimum size) and subsequently re-open it.

The style of the hot zone used is specified by the HotZone property of TcxCustomSplitter descendants. This property can hold a TcxHotZoneStyle descendant object representing the hot zone style. There are four descendants shipped – TcxSimpleStyle, TcxMediaPlayer8Style, TcxMediaPlayer9Style and TcxXPTaskBarStyle. However, you can also create your own descendant if you need a custom hot zone style. This topic describes how to perform this.

If you need to create a custom hot zone style, derive an object from the TcxHotZoneStyle. The table below lists the members that need to be overridden or must be used when implementing your object’s functionality.

Member Description
Changed This method tells the owning splitter control to invalidate its hot zone. Call this method whenever changing settings which affect the hot zone’s appearance.
SplitterDirection Gets a value indicating the orientation of the splitter. Use this method to determine whether the splitter is oriented vertically or horizontally.
CalculateHotZoneRect This method is called whenever the bounding rectangle of the hot zone needs to be obtained (for instance, when passing the bounding rectangle of the hot zone to the DrawHotZone method). As implemented in the TcxHotZoneStyle class, this method calculates the bounding rectangle according to the SizePercent property value. Override this method if you need to correct the hot zone’s bounding rectangle.
DrawHotZone This method is called whenever the hot zone needs to be repainted. Override it to paint the hot zone as desired.

The following code declares a TcxHotZoneStyle descendant. This descendant paints the hot zone as a button. The button is flat in normal state. If it is hot-tracked or pressed, it is painted raised and lowered respectively. The descendant created provides a ButtonColor property to specify the color of the button. When the property value changes, the Changed method is called to invalidate the hot zone.

The descendant also overrides the CalculateHotZoneRect method. This is used to decrease the width of the hot zone if it is vertically oriented. If the hot zone is horizontally oriented, the height is decreased. The SplitterDirection method is used to determine the hot zone orientation.

TcxCustomButtonHotZoneStyle = class(TcxHotZoneStyle)
private
  FButtonColor: TColor;
  procedure SetButtonColor(Value: TColor);
protected
  function CalculateHotZoneRect(const ABounds: TRect): TRect; override;
  function DrawHotZone(ACanvas: TcxCanvas; const ARect: TRect; const AHighlighted, AClicked: Boolean): TRect; override;
  procedure DrawBackground(ACanvas: TcxCanvas; const ARect: TRect; const AHighlighted, AClicked: Boolean); override;
public
  constructor Create(AOwner: TcxCustomSplitter); override;
published
  property ButtonColor: TColor read FButtonColor write SetButtonColor;
  property SizePercent;
end;
// ...
procedure TcxCustomButtonHotZoneStyle.SetButtonColor(Value: TColor);
begin
  if Value = FButtonColor then Exit;
  FButtonColor := Value;
  Changed;
end;
constructor TcxCustomButtonHotZoneStyle.Create(AOwner: TcxCustomSplitter);
begin
  inherited Create(AOwner);
  FButtonColor := clBtnFace;
end;
function TcxCustomButtonHotZoneStyle.CalculateHotZoneRect(const ABounds: TRect): TRect;
begin
  // obtaining the default bounding rectangle of the hot zone
  Result := inherited CalculateHotZoneRect(ABounds);
  if (SplitterDirection = cxsdLeftToRight) or (SplitterDirection = cxsdRightToLeft) then
  begin
    // splitter is vertically oriented, its width is decreased
    Inc(Result.Left);
    Dec(Result.Right);
  end
  else
    // splitter is horizontally oriented, its height is decreased
    Inc(Result.Top);
    Dec(Result.Bottom);
  begin
  end;
end;
function TcxCustomButtonHotZoneStyle.DrawHotZone(ACanvas: TcxCanvas; const ARect: TRect; const AHighlighted, AClicked: Boolean): TRect;
var
  ATopLeftBorderColor, ABottomRightBorderColor: TColor;
  ABounds: TRect;
begin
  // specifying button's border colors
  if AHighlighted then
  begin
    ATopLeftBorderColor := clBtnHighlight;
    ABottomRightBorderColor := clBtnShadow;
  end;
  if AClicked then
  begin
    ATopLeftBorderColor := clBtnShadow;
    ABottomRightBorderColor := clBtnHighlight;
  end;
  if not (AHighlighted or AClicked) then
  begin
    ATopLeftBorderColor := clBtnShadow;
    ABottomRightBorderColor := clBtnShadow;
  end;
  ABounds := CalculateHotZoneRect(ARect);
  // painting the borders
  ACanvas.FrameRect(ABounds, ATopLeftBorderColor, 1, [bLeft, bTop]);
  ACanvas.FrameRect(ABounds, ABottomRightBorderColor, 1, [bBottom, bRight]);
  // filling the button's client area
  ACanvas.Brush.Color := FButtonColor;
  ACanvas.Brush.Style := bsSolid;
  ABounds.TopLeft := Point(ABounds.Left + 1, ABounds.Top + 1);
  ABounds.BottomRight := Point(ABounds.Right - 1, ABounds.Bottom - 1);
  ACanvas.FillRect(ABounds);
end;
procedure TcxCustomButtonHotZoneStyle.DrawBackground(ACanvas: TcxCanvas; const ARect: TRect; const AHighlighted, AClicked: Boolean);
begin
  ACanvas.Brush.Color := clYellow;
  ACanvas.FillRect(ARect);
end;

After the code is written, you can assign this hot zone style to a splitter control using the following code lines.

cxSplitter1.HotZoneStyleClass := TcxCustomButtonHotZoneStyle;
(cxSplitter1.HotZone as TcxCustomButtonHotZoneStyle).ButtonColor := clMoneyGreen;

The image below shows the appearance the hot zone will have in the normal, highlighted and clicked states, respectively.

Note that you can also make use of the new hot zone style at design time. To implement this, perform the following steps:

  • Move the TcxCustomButtonHotZoneStyle class declaration to the cxSplitter.pas unit.

  • Add the following line to the initialization section of the unit:

GetRegisteredHotZoneStyles.Register(TcxCustomButtonHotZoneStyle, 'Button');
  • Add the following line to the finalization section of the unit:
GetRegisteredHotZoneStyles.UnRegister(TcxCustomButtonHotZoneStyle);
  • Recompile the package containing the unit.

After doing this, you can choose the Button hot zone style from the HotZone combo box at design time.

If the Button style is selected, you can expand the HotZone property to access the published properties of the TcxCustomButtonHotZoneStyle class. These are the ButtonColor and SizePercent properties. You can change them to change the color of the button and its size relative to the splitter control.

See Also