DELPHI FAQ: Изменить цвет TButton


Изменить цвет TButton
Previous  Home  Next




  You cannot change the color of a standard TButton, 
  since the windows button control always paints itself with the 
  button color defined in the control panel. 
  But you can derive derive a new component from TButton and handle 
  the and drawing behaviour there. 
}
 


unit
 ColorButton; 

interface
 

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

type
 
  TDrawButtonEvent = procedure
(Control: TWinControl; 
    Rect: TRect; State: TOwnerDrawState) of
 object

  TColorButton = class
(TButton) 
  private
 
    FCanvas: TCanvas; 
    IsFocused: Boolean; 
    FOnDrawButton: TDrawButtonEvent; 
  protected
 
    procedure
 CreateParams(var Params: TCreateParams); override
    procedure
 SetButtonStyle(ADefault: Boolean); override
    procedure
 CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED; 
    procedure
 CMFontChanged(var Message: TMessage); message CM_FONTCHANGED; 
    procedure
 CNMeasureItem(var Message: TWMMeasureItem); message CN_MEASUREITEM; 
    procedure
 CNDrawItem(var Message: TWMDrawItem); message CN_DRAWITEM; 
    procedure
 WMLButtonDblClk(var Message: TWMLButtonDblClk); message WM_LBUTTONDBLCLK; 
    procedure
 DrawButton(Rect: TRect; State: UINT); 
  public
 
    constructor
 Create(AOwner: TComponent); override
    destructor
 Destroy; override
    property
 Canvas: TCanvas read FCanvas; 
  published
 
    property
 OnDrawButton: TDrawButtonEvent read FOnDrawButton write FOnDrawButton; 
    property
 Color; 
  end


procedure
 Register

implementation
 

procedure
 Register
begin
 
  RegisterComponents('Samples'
, [TColorButton]); 
end


constructor
 TColorButton.Create(AOwner: TComponent); 
begin
 
  inherited
 Create(AOwner); 
  FCanvas := TCanvas.Create; 
end


destructor
 TColorButton.Destroy; 
begin
 
  inherited
 Destroy; 
  FCanvas.Free; 
end


procedure
 TColorButton.CreateParams(var Params: TCreateParams); 
begin
 
  inherited
 CreateParams(Params); 
  with
 Params do Style := Style or BS_OWNERDRAW; 
end


procedure
 TColorButton.SetButtonStyle(ADefault: Boolean); 
begin
 
  if
 ADefault <> IsFocused then 
  begin
 
    IsFocused := ADefault; 
    Refresh; 
  end

end


procedure
 TColorButton.CNMeasureItem(var Message: TWMMeasureItem); 
begin
 
  with
 Message.MeasureItemStruct^ do 
  begin
 
    itemWidth  := Width; 
    itemHeight := Height; 
  end

end


procedure
 TColorButton.CNDrawItem(var Message: TWMDrawItem); 
var
 
  SaveIndex: Integer; 
begin
 
  with
 Message.DrawItemStruct^ do 
  begin
 
    SaveIndex := SaveDC(hDC); 
    FCanvas.Lock; 
    try
 
      FCanvas.Handle := hDC; 
      FCanvas.Font := Font; 
      FCanvas.Brush := Brush; 
      DrawButton(rcItem, itemState); 
    finally
 
      FCanvas.Handle := 0

      FCanvas.Unlock; 
      RestoreDC(hDC, SaveIndex); 
    end

  end

  Message
.Result := 1
end


procedure
 TColorButton.CMEnabledChanged(var Message: TMessage); 
begin
 
  inherited

  Invalidate; 
end


procedure
 TColorButton.CMFontChanged(var Message: TMessage); 
begin
 
  inherited

  Invalidate; 
end


procedure
 TColorButton.WMLButtonDblClk(var Message: TWMLButtonDblClk); 
begin
 
  Perform(WM_LBUTTONDOWN, Message
.Keys, Longint(Message.Pos)); 
end


procedure
 TColorButton.DrawButton(Rect: TRect; State: UINT); 
var
 
  Flags, OldMode: Longint; 
  IsDown, IsDefault, IsDisabled: Boolean; 
  OldColor: TColor; 
  OrgRect: TRect; 
begin
 
  OrgRect := Rect; 
  Flags := DFCS_BUTTONPUSH or
 DFCS_ADJUSTRECT; 
  IsDown := State and
 ODS_SELECTED <> 0
  IsDefault := State and
 ODS_FOCUS <> 0
  IsDisabled := State and
 ODS_DISABLED <> 0

  if
 IsDown then Flags := Flags or DFCS_PUSHED; 
  if
 IsDisabled then Flags := Flags or DFCS_INACTIVE; 

  if
 IsFocused or IsDefault then 
  begin
 
    FCanvas.Pen.Color := clWindowFrame; 
    FCanvas.Pen.Width := 1

    FCanvas.Brush.Style := bsClear; 
    FCanvas.Rectangle(Rect.Left, Rect.Top, Rect.Right, Rect.Bottom); 
    InflateRect(Rect, - 1
, - 1); 
  end


  if
 IsDown then 
  begin
 
    FCanvas.Pen.Color := clBtnShadow; 
    FCanvas.Pen.Width := 1

    FCanvas.Brush.Color := clBtnFace; 
    FCanvas.Rectangle(Rect.Left, Rect.Top, Rect.Right, Rect.Bottom); 
    InflateRect(Rect, - 1
, - 1); 
  end
 
  else
 
    DrawFrameControl(FCanvas.Handle, Rect, DFC_BUTTON, Flags); 

  if
 IsDown then OffsetRect(Rect, 11); 

  OldColor := FCanvas.Brush.Color; 
  FCanvas.Brush.Color := Color; 
  FCanvas.FillRect(Rect); 
  FCanvas.Brush.Color := OldColor; 
  OldMode := SetBkMode(FCanvas.Handle, TRANSPARENT); 
  FCanvas.Font.Color := clBtnText; 
  if
 IsDisabled then 
    DrawState(FCanvas.Handle, FCanvas.Brush.Handle, nil
, Integer(Caption), 0
    ((Rect.Right - Rect.Left) - FCanvas.TextWidth(Caption)) div
 2
    ((Rect.Bottom - Rect.Top) - FCanvas.TextHeight(Caption)) div
 2
      0
0, DST_TEXT or DSS_DISABLED) 
  else
 
    DrawText(FCanvas.Handle, PChar(Caption), - 1
, Rect, 
      DT_SINGLELINE or
 DT_CENTER or DT_VCENTER); 
  SetBkMode(FCanvas.Handle, OldMode); 

  if
 Assigned(FOnDrawButton) then 
    FOnDrawButton(Self, Rect, TOwnerDrawState(LongRec(State).Lo)); 

  if
 IsFocused and IsDefault then 
  begin
 
    Rect := OrgRect; 
    InflateRect(Rect, - 4
, - 4); 
    FCanvas.Pen.Color := clWindowFrame; 
    FCanvas.Brush.Color := clBtnFace; 
    DrawFocusRect(FCanvas.Handle, Rect); 
  end

end

end
.


В книгах Калверта, Свана и других авторов можно найти похожий текст. Смысл текста – "Изменить цвет кнопок Button, BitBtn нельзя, т.к. их рисует WINDOWS". Если нельзя, но ОЧЕНЬ НУЖНО, то можно.

Небольшой компонент ColorBtn, дает возможность использовать в кнопках цвет. Кроме того, представлено новое свойство - Frame3D, позволяющее получить более реалистичный вид нажатой кнопки. В отличие от API, при изменении значения свойства Frame3D, не требуется переоткрытие компонента.

Примечание. Кнопку по-прежнему рисует WINDOWS, а раскрашивает ее ColorBtn. Код компонента на 90% повторяет код BitBtn, ничего необычного здесь нет. Чаще заглядывайте в VCL - можно найти много интересного. На рисунке представлены ColorButton и ColorBitBtn.



unit colorbtn;

interface


uses


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

type


  TColorBtn = class
(TButton)
  private

    FCanvas: TCanvas;
    IsFocused: Boolean;
    F3DFrame: boolean;
    FButtonColor: TColor;
    procedure
 Set3DFrame(Value: boolean);
    procedure
 SetButtonColor(Value: TColor);
    procedure
 CNDrawItem(var Message: TWMDrawItem); message CN_DRAWITEM;
    procedure
 WMLButtonDblClk(var Message: TWMLButtonDblClk); message
      WM_LBUTTONDBLCLK;
    procedure
 DrawButtonText(const Caption: string; TRC: TRect; State:
      TButtonState; BiDiFlags: Longint);
    procedure
 CalcuateTextPosition(const Caption: stringvar TRC: TRect;
      BiDiFlags: Longint);
  protected

    procedure
 CreateParams(var Params: TCreateParams); override;
    procedure
 SetButtonStyle(ADefault: Boolean); override;
  public

    constructor
 Create(AOwner: TComponent); override;
    destructor
 Destroy; override;
  published

    property
 ButtonColor: TColor read FButtonColor write SetButtonColor default
      clBtnFace;
    property
 Frame3D: boolean read F3DFrame write Set3DFrame default False;
  end
;

procedure
 Register;

implementation


{ TColorBtn }


constructor
 TColorBtn.Create(AOwner: TComponent);
begin

  inherited
 Create(AOwner);
  Height := 21
;
  FCanvas := TCanvas.Create;
  FButtonColor := clBtnFace;
  F3DFrame := False;
end
;

destructor
 TColorBtn.Destroy;
begin

  FCanvas.Free;
  inherited
 Destroy;
end
;

procedure
 TColorBtn.CreateParams(var Params: TCreateParams);
begin

  inherited
 CreateParams(Params);
  with
 Params do
    Style := Style or
 BS_OWNERDRAW;
end
;

procedure
 TColorBtn.Set3DFrame(Value: boolean);
begin

  if
 F3DFrame <> Value then
    F3DFrame := Value;
end
;

procedure
 TColorBtn.SetButtonColor(Value: TColor);
begin

  if
 FButtonColor <> Value then
  begin

    FButtonColor := Value;
    Invalidate;
  end
;
end
;

procedure
 TColorBtn.WMLButtonDblClk(var Message: TWMLButtonDblClk);
begin

  Perform(WM_LBUTTONDOWN, Message
.Keys, Longint(Message.Pos));
end
;

procedure
 TColorBtn.SetButtonStyle(ADefault: Boolean);
begin

  if
 IsFocused <> ADefault then
    IsFocused := ADefault;
end
;

procedure
 TColorBtn.CNDrawItem(var Message: TWMDrawItem);
var

  RC: TRect;
  Flags: Longint;
  State: TButtonState;
  IsDown, IsDefault: Boolean;
  DrawItemStruct: TDrawItemStruct;
begin

  DrawItemStruct := Message
.DrawItemStruct^;
  FCanvas.Handle := DrawItemStruct.HDC;
  RC := ClientRect;
  with
 DrawItemStruct do
  begin

    IsDown := ItemState and
 ODS_SELECTED <> 0;
    IsDefault := ItemState and
 ODS_FOCUS <> 0;
    if
 not Enabled then
      State := bsDisabled
    else
 if IsDown then
      State := bsDown
    else

      State := bsUp;
  end
;
  Flags := DFCS_BUTTONPUSH or
 DFCS_ADJUSTRECT;
  if
 IsDown then
    Flags := Flags or
 DFCS_PUSHED;
  if
 DrawItemStruct.ItemState and ODS_DISABLED <> 0 then
    Flags := Flags or
 DFCS_INACTIVE;
  if
 IsFocused or IsDefault then
  begin

    FCanvas.Pen.Color := clWindowFrame;
    FCanvas.Pen.Width := 1
;
    FCanvas.Brush.Style := bsClear;
    FCanvas.Rectangle(RC.Left, RC.Top, RC.Right, RC.Bottom);
    InflateRect(RC, -1
, -1);
  end
;
  if
 IsDown then
  begin

    FCanvas.Pen.Color := clBtnShadow;
    FCanvas.Pen.Width := 1
;
    FCanvas.Rectangle(RC.Left, RC.Top, RC.Right, RC.Bottom);
    InflateRect(RC, -1
, -1);
    if
 F3DFrame then
    begin

      FCanvas.Pen.Color := FButtonColor;
      FCanvas.Pen.Width := 1
;
      DrawFrameControl(DrawItemStruct.HDC, RC, DFC_BUTTON, Flags);
    end
;
  end

  else

    DrawFrameControl(DrawItemStruct.HDC, RC, DFC_BUTTON, Flags);
  FCanvas.Brush.Color := FButtonColor;
  FCanvas.FillRect(RC);
  InflateRect(RC, 1
1);
  if
 IsFocused then
  begin

    RC := ClientRect;
    InflateRect(RC, -1
, -1);
  end
;
  FCanvas.Font := Self.Font;
  if
 IsDown then
    OffsetRect(RC, 1
1);
  DrawButtonText(Caption, RC, State, 0
);
  if
 IsFocused and IsDefault then
  begin

    RC := ClientRect;
    InflateRect(RC, -4
, -4);
    FCanvas.Pen.Color := clWindowFrame;
    Windows.DrawFocusRect(FCanvas.Handle, RC);
  end
;
  FCanvas.Handle := 0
;
end
;

procedure
 TColorBtn.CalcuateTextPosition(const Caption: stringvar TRC: TRect;
  BiDiFlags: Integer);
var

  TB: TRect;
  TS, TP: TPoint;
begin

  with
 FCanvas do
  begin

    TB := Rect(0
0, TRC.Right + TRC.Left, TRC.Top + TRC.Bottom);
    DrawText(Handle, PChar(Caption), Length(Caption), TB, DT_CALCRECT or

      BiDiFlags);
    TS := Point(TB.Right - TB.Left, TB.Bottom - TB.Top);
    TP.X := ((TRC.Right - TRC.Left) - TS.X + 1
div 2;
    TP.Y := ((TRC.Bottom - TRC.Top) - TS.Y + 1
div 2;
    OffsetRect(TB, TP.X + TRC.Left, TP.Y + TRC.Top);
    TRC := TB;
  end
;
end
;

procedure
 TColorBtn.DrawButtonText(const Caption: string; TRC: TRect; State:
  TButtonState; BiDiFlags: Integer);
begin

  with
 FCanvas do
  begin

    CalcuateTextPosition(Caption, TRC, BiDiFlags);
    Brush.Style := bsClear;
    if
 State = bsDisabled then
    begin

      OffsetRect(TRC, 1
1);
      Font.Color := clBtnHighlight;
      DrawText(Handle, PChar(Caption), Length(Caption), TRC,
        DT_CENTER or
 DT_VCENTER or BiDiFlags);
      OffsetRect(TRC, -1
, -1);
      Font.Color := clBtnShadow;
      DrawText(Handle, PChar(Caption), Length(Caption), TRC,
        DT_CENTER or
 DT_VCENTER or BiDiFlags);
    end

    else

      DrawText(Handle, PChar(Caption), Length(Caption), TRC,
        DT_CENTER or
 DT_VCENTER or BiDiFlags);
  end
;
end
;

procedure
 Register;
begin

  RegisterComponents('Controls'
, [TColorBtn]);
end
;

end
.




Небольшое дополнение. Кнопку по прежнему рисует WINDOWS, а раскрашивает ее ColorBtn. Код компонента на 90% повторяет код BitBtn, ничего необычного здесь нет. Хочется повторить слова Калверта – "Пользуйтесь исходным кодом". Чаще заглядывайте в VCL - можно найти много интересного.


Взято с www.delphiworld.narod.ru





DELPHI FAQ




EOMY TOP 100      Рейтинг@Mail.ru      Rambler's Top100



Новости печати. фото?: Print Fotomag | Ковровые покрытия киев ламинат киев водяной теплый пол.
Бесплатный хостинг от EOMY.NET