Модераторы: Snowy, MetalFan, bems, Poseidon
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Собственная отрисовка TButton и ThemeServices 
:(
    Опции темы
MikeLevinN
Дата 28.12.2007, 12:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 21
Регистрация: 6.9.2007

Репутация: нет
Всего: нет



У меня есть исправленный наследник TButton, с собственной отрисовской. Для прмера - хорошо известный в интернете код: цветной TButton.

Код

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, 1, 1); 

  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.


Как в данный код вставить поддержку ThemeServices? (Что бы при включенных темах в Windows кнопка отрисовывалась стандартно как в теме, при отключенных - не стандартно) Я думал, что можно где-то вставить условие if ThemeServices.ThemesEnabled и вызывать inherited предка, но оказалось не все так просто: я не представляю где и как такое сделать.

И второй вопрос, не совсем по теме правда, - про приведенный выше код: при TButton.Enabled = False, происходит сдвиг надписи на кнопке, она становится выше и правее. Как это побороть?


Спасибо.
PM MAIL   Вверх
ivan219
  Дата 28.12.2007, 20:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1121
Регистрация: 19.11.2005
Где: Планета земля

Репутация: 5
Всего: 12



Цитата(MikeLevinN @  28.12.2007,  12:24 Найти цитируемый пост)
И второй вопрос,

Зделать вот так:
Код

procedure TColorButton.DrawButton(Rect: TRect; State: UINT);
.
.
.
  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,
.
.
.


PM MAIL ICQ   Вверх
MikeLevinN
Дата 28.12.2007, 20:40 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 21
Регистрация: 6.9.2007

Репутация: нет
Всего: нет



ivan219, в таком случае сама надпись на кнопке не будет ссответствовать положению - она всегда будет активна.

"Ошибка" где-то здесь:
Код

    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)


Я могу конечно  попробовать подогнать надпись Rect.Left + ... но как-то не слишком надежно, мне кажется.
PM MAIL   Вверх
ivan219
  Дата 29.12.2007, 16:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1121
Регистрация: 19.11.2005
Где: Планета земля

Репутация: 5
Всего: 12



Цитата(MikeLevinN @  28.12.2007,  20:40 Найти цитируемый пост)
ivan219, в таком случае сама надпись на кнопке не будет ссответствовать положению - она всегда будет активна.

Виноват поспешил smile 
Код

    ((Rect.Right - Rect.Left) - FCanvas.TextWidth(Caption)) div 2 + 2,
    ((Rect.Bottom - Rect.Top) - FCanvas.TextHeight(Caption)) div 2 + 2,

PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Для новичков"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.1002 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.