Reputation: 13
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
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 TControl
s. 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