Delphify
Delphify

Reputation: 13

Delphi image button, no caption, no border with a tabstop

I want to use an image as a button that has no caption, no background and no border with a tabstop.

I have tried the speedbutton with the flat property set which is perfect except it has no tabstop.

I have tried the bitbtn which also accepts an image and has a tabstop but has no way to remove the button border. I have unchecked seBorder in StyleElements which does nothing and there is no flat option so cannot remove the border.

Upvotes: 0

Views: 573

Answers (1)

W. Chang
W. Chang

Reputation: 502

We all have personal styles and preferences, but when it comes to UI design, it is important to stick with the platform standard. And note that your UI may become an unusable headache in the future. Things like the introduction of the Aero interface and the use of high-density monitors can easily mess up your personalized UI.

With that said, TSpeedButton and TBitBtn are two options to implement what you want. By design, Delphi has two types of TControls. One is TGraphicControl, like TSpeedButton, which cannot receive the focus. The other is TWinControl, like TBitBtn, which can be focused. So, one way to do it is to place a TSpeedButton on a focusable container, make the container transparent by overriding CreateParam, and handle its keypress/keydown events. It is not easy though. Alternatively, you can sub-class TBitBtn and override its drawing, by handling the CN_DRAWITEM message.

Below is a minimal working example, tested on Delphi 2009 and 10.4. Since you want only the image, I skipped and didn't deal with theme. I also didn't handle button down, enabled, and hovering. Read the source code (Buttons.pas) for how to deal with them.

Add a TButton and a TbitBtn to a new form and try this code

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  Buttons, StdCtrls;

type
  // This changes all TBitBtn controls in this form, including the one from the plaette
  TBitBtn = class(Buttons.TBitBtn)
  private
    procedure CNDrawItem(var Message: TWMDrawItem); message CN_DRAWITEM;
    procedure DrawItem(const DrawItemStruct: TDrawItemStruct);
  end;

  TForm1 = class(TForm)
    BitBtn1: TBitBtn;
    Button1: TButton;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TBitBtn }

procedure TBitBtn.CNDrawItem(var Message: TWMDrawItem);
begin
  DrawItem(Message.DrawItemStruct^);
end;

procedure TBitBtn.DrawItem(const DrawItemStruct: TDrawItemStruct);
var
  R: TRect;
  FCanvas: TCanvas;
begin
  FCanvas := TCanvas.Create;
  try
    FCanvas.Handle := DrawItemStruct.hDC;
    R := ClientRect;
    if Focused then
      FCanvas.DrawFocusRect(R);
    Glyph.Transparent := True;
    FCanvas.Draw((R.Left + R.Right - GlyPh.Width) div 2,
                 (R.Top + R.Bottom - GlyPh.Height) div 2,
                 GlyPh);
  finally
    FCanvas.Free;
  end;
end;

end.

Edit: 26 Mar 2023: TBitBtn's Glyph is drawn with transparent background, although its Transparent property is false. A line was added above to make the drawing transparent, like TBitBtn does.

Upvotes: 0

Related Questions