I'm looking for an out-of-the-box way of configuring a flat borderless button. So that I can add a button from palette and configure it in design-time, without runtime overrides. I can use DevExpress components, however I would like to avoid LookAndFeel overrides or creating a custom theme for that.
The problem is that some controls allow to edit properties, but miss others.
Here's what I have tried:
Component TabStop FocusRect Text V.Align Borderless Color
----------------------------------------------------------------------------
TButton V V V - -
TSpeedButton V V V - -
TLabel - - V V V
TPanel V - V V V
TStaticText V - - V V
TcxButton V V V - V
TcxLabel - - V V V
----------------------------------------------------------------------------
* Text V.Align - vertical text alignment to center
* Borderless - no borders in default/unfocused state
** Color - ability to set face color
Another approach could be to override a TButton class via some OwnerDraw magic and put that unit first into every forms' uses clause?
Do you know of any alternatives that would allow to create/configure such a flat button in designtime having only standard Delphi 7 and basic DevExpress components?
EDIT: To address downvoters, who presumably think this is a bad question because it asks how to do something with existing tools without reinventing the bicycle.
P.S. Target OS is Windows XP and up
Below is an interposer class example that modifies TButton
to be of BS_OWNERDRAW
style. As you noted, it can be put into a unit that is to be used after 'stdctrls'.
type
TButton = class(stdctrls.TButton)
protected
procedure SetButtonStyle(ADefault: Boolean); override;
procedure CNCtlcolorbtn(var Message: TMessage); message CN_CTLCOLORBTN;
procedure CNDrawitem(var Message: TWMDrawItem); message CN_DRAWITEM;
procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
end;
...
procedure TButton.SetButtonStyle(ADefault: Boolean);
begin
if HandleAllocated then
Perform(BM_SETSTYLE, BS_OWNERDRAW, 1);
end;
procedure TButton.CNCtlcolorbtn(var Message: TMessage);
begin
DWORD(Message.Result) := CreateSolidBrush($79FF);
end;
procedure TButton.CNDrawitem(var Message: TWMDrawItem);
var
DC: HDC;
SaveObj: HGDIOBJ;
R: TRect;
begin
R := ClientRect;
DC := Message.DrawItemStruct.hDC;
SaveObj := SelectObject(DC, Font.Handle);
SetBkMode(DC, TRANSPARENT);
DrawText(DC, PChar(Caption), -1, R, DT_SINGLELINE or DT_CENTER or DT_VCENTER);
SelectObject(DC, SaveObj);
Message.Result := 1;
end;
procedure TButton.WMPaint(var Message: TWMPaint);
var
DC: HDC;
R: TRect;
begin
inherited;
if GetFocus = Handle then begin
DC := GetDC(Handle);
SelectObject(DC, GetStockObject(DC_BRUSH));
SetDCBrushColor(DC, $FF);
R := ClientRect;
InflateRect(R, -2, -2);
FrameRect(DC, R, DC_BRUSH);
ReleaseDC(Handle, DC);
end;
end;
Looks on W7 like this: