кнопка закрытия вкладки, не поддерживающая стили vcl

Я использовал код, приведенный в этом примереКак реализовать кнопку закрытия для TTabsheet из TPageControl нарисовать кнопку закрытия на каждой вкладке элемента управления страницы, и я заменил ThemeServices на Style Services внутри кода, и при применении стилей кнопка закрытия не отображается и никак не реагирует. Может ли кто-нибудь указать мне другой путь решения этой проблемы. благодарю вас! это код события OnDrawTab:

<code>  procedure TFormMain.PageControlCloseButtonDrawTab(Control: TCustomTabControl;
  TabIndex: Integer; const Rect: TRect; Active: Boolean);
var
  CloseBtnSize: Integer;
  PageControl: TPageControl;
  TabCaption: TPoint;
  CloseBtnRect: TRect;
  CloseBtnDrawState: Cardinal;
  CloseBtnDrawDetails: TThemedElementDetails;
begin
  PageControl := Control as TPageControl;

  if InRange(TabIndex, 0, Length(FCloseButtonsRect) - 1) then
  begin
    CloseBtnSize := 14;
    TabCaption.Y := Rect.Top + 3;

    if Active then
    begin
      CloseBtnRect.Top := Rect.Top + 4;
      CloseBtnRect.Right := Rect.Right - 5;
      TabCaption.X := Rect.Left + 6;
    end
    else
    begin
      CloseBtnRect.Top := Rect.Top + 3;
      CloseBtnRect.Right := Rect.Right - 5;
      TabCaption.X := Rect.Left + 3;
    end;

    CloseBtnRect.Bottom := CloseBtnRect.Top + CloseBtnSize;
    CloseBtnRect.Left := CloseBtnRect.Right - CloseBtnSize;
    FCloseButtonsRect[TabIndex] := CloseBtnRect;

    PageControl.Canvas.FillRect(Rect);
    PageControl.Canvas.TextOut(TabCaption.X, TabCaption.Y, PageControl.Pages[TabIndex].Caption);

    if not UseThemes then
    begin
      if (FCloseButtonMouseDownIndex = TabIndex) and FCloseButtonShowPushed then
        CloseBtnDrawState := DFCS_CAPTIONCLOSE + DFCS_PUSHED
      else
        CloseBtnDrawState := DFCS_CAPTIONCLOSE;

      Winapi.Windows.DrawFrameControl(PageControl.Canvas.Handle,
        FCloseButtonsRect[TabIndex], DFC_CAPTION, CloseBtnDrawState);
    end
    else
    begin
      Dec(FCloseButtonsRect[TabIndex].Left);

      if (FCloseButtonMouseDownIndex = TabIndex) and FCloseButtonShowPushed then
        CloseBtnDrawDetails := StyleServices.GetElementDetails(twCloseButtonPushed)
      else
        CloseBtnDrawDetails := StyleServices.GetElementDetails(twCloseButtonNormal);

      StyleServices.DrawElement(PageControl.Canvas.Handle, CloseBtnDrawDetails,
        FCloseButtonsRect[TabIndex]);
    end;
  end;
end;
</code>
 TLama10 мая 2012 г., 11:58
Это потому, что у стилей VCL есть своиDrawTab метод. Вы должны создать свой собственный хук в стиле VCL и дополнительно нарисовать эти кнопки закрытия.

Ответы на вопрос(2)

и я получил его, работая над Metro UI на Delphi XE6.

Мой обходной путь для получения правильного расстояния между именем вкладки и кнопкой должен был изменить эту строку

Result.Left := Result.Right - (ButtonR.Width);
//it was   Result.Left := Result.Right - (ButtonR.Width) -5;

И установка большего TabWith в свойствах PageController.

Кроме того, напомните, что «Регистрация» линии, идет на класс инициализации прямо перед концом блока.

 //...all the code of the unit

Initialization

TStyleManager.Engine.RegisterStyleHook(TCustomTabControl,
  TTabControlStyleHookBtnClose);
TStyleManager.Engine.RegisterStyleHook(TTabControl,
  TTabControlStyleHookBtnClose);

end.//final unit "end" =D
Решение Вопроса

вы должны написать хук стиля vcl, чтобы нарисовать кнопку закрытия в элементах управления вкладки, взгляните наVcl.Styles.ColorTabs блок (представлен в этих статьяхСоздание красочных таблиц с помощью стилей VCL, Добавлена граница для TTabColorControlStyleHook) чтобы иметь представление о том, что вам нужно, чтобы написать стиль хук, как это. В дополнение к коду для рисования кнопки во вкладках вы должны обработать сообщения WM_MOUSEMOVE и WM_LBUTTONUP (в хуке стиля), чтобы изменить состояние кнопки (обычное, горячее) и обнаружить щелчок в кнопке закрытия.

Если у вас есть проблемы с реализацией хука стиля, дайте мне знать, чтобы опубликовать полное решение здесь.

UPDATE

Я только что написал этот простой стиль хук, чтобы добавить suport для кнопки закрытия в таблицах.

uses
  Vcl.Styles,
  Vcl.Themes;

type
  TTabControlStyleHookBtnClose = class(TTabControlStyleHook)
  private
    FHotIndex       : Integer;
    FWidthModified  : Boolean;
    procedure WMMouseMove(var Message: TMessage); message WM_MOUSEMOVE;
    procedure WMLButtonUp(var Message: TWMMouse); message WM_LBUTTONUP;
    function GetButtonCloseRect(Index: Integer):TRect;
  strict protected
    procedure DrawTab(Canvas: TCanvas; Index: Integer); override;
    procedure MouseEnter; override;
    procedure MouseLeave; override;
  public
    constructor Create(AControl: TWinControl); override;
  end;

constructor TTabControlStyleHookBtnClose.Create(AControl: TWinControl);
begin
  inherited;
  FHotIndex:=-1;
  FWidthModified:=False;
end;

procedure TTabControlStyleHookBtnClose.DrawTab(Canvas: TCanvas; Index: Integer);
var
  Details : TThemedElementDetails;
  ButtonR : TRect;
  FButtonState: TThemedWindow;
begin
  inherited;

  if (FHotIndex>=0) and (Index=FHotIndex) then
   FButtonState := twSmallCloseButtonHot
  else
  if Index = TabIndex then
   FButtonState := twSmallCloseButtonNormal
  else
   FButtonState := twSmallCloseButtonDisabled;

  Details := StyleServices.GetElementDetails(FButtonState);

  ButtonR:= GetButtonCloseRect(Index);
  if ButtonR.Bottom - ButtonR.Top > 0 then
   StyleServices.DrawElement(Canvas.Handle, Details, ButtonR);
end;

procedure TTabControlStyleHookBtnClose.WMLButtonUp(var Message: TWMMouse);
Var
  LPoint : TPoint;
  LIndex : Integer;
begin
  LPoint:=Message.Pos;
  for LIndex := 0 to TabCount-1 do
   if PtInRect(GetButtonCloseRect(LIndex), LPoint) then
   begin
      if Control is TPageControl then
      begin
        TPageControl(Control).Pages[LIndex].Parent:=nil;
        TPageControl(Control).Pages[LIndex].Free;
      end;
      break;
   end;
end;

procedure TTabControlStyleHookBtnClose.WMMouseMove(var Message: TMessage);
Var
  LPoint : TPoint;
  LIndex : Integer;
  LHotIndex : Integer;
begin
  inherited;
  LHotIndex:=-1;
  LPoint:=TWMMouseMove(Message).Pos;
  for LIndex := 0 to TabCount-1 do
   if PtInRect(GetButtonCloseRect(LIndex), LPoint) then
   begin
      LHotIndex:=LIndex;
      break;
   end;

   if (FHotIndex<>LHotIndex) then
   begin
     FHotIndex:=LHotIndex;
     Invalidate;
   end;
end;

function TTabControlStyleHookBtnClose.GetButtonCloseRect(Index: Integer): TRect;
var
  FButtonState: TThemedWindow;
  Details : TThemedElementDetails;
  R, ButtonR : TRect;
begin
  R := TabRect[Index];
  if R.Left < 0 then Exit;

  if TabPosition in [tpTop, tpBottom] then
  begin
    if Index = TabIndex then
      InflateRect(R, 0, 2);
  end
  else
  if Index = TabIndex then
    Dec(R.Left, 2)
  else
    Dec(R.Right, 2);

  Result := R;
  FButtonState := twSmallCloseButtonNormal;

  Details := StyleServices.GetElementDetails(FButtonState);
  if not StyleServices.GetElementContentRect(0, Details, Result, ButtonR) then
    ButtonR := Rect(0, 0, 0, 0);

  Result.Left :=Result.Right - (ButtonR.Width) - 5;
  Result.Width:=ButtonR.Width;
end;

procedure TTabControlStyleHookBtnClose.MouseEnter;
begin
  inherited;
  FHotIndex := -1;
end;

procedure TTabControlStyleHookBtnClose.MouseLeave;
begin
  inherited;
  if FHotIndex >= 0 then
  begin
    FHotIndex := -1;
    Invalidate;
  end;
end;

Зарегистрируйтесь таким образом

  TStyleManager.Engine.RegisterStyleHook(TCustomTabControl, TTabControlStyleHookBtnClose);
  TStyleManager.Engine.RegisterStyleHook(TTabControl, TTabControlStyleHookBtnClose);

И это демо

enter image description here

 26 янв. 2015 г., 22:32
@JerryDodge, это очень простая реализация, вы можете решить проблему, пересчитав ширину вкладок.
 26 янв. 2015 г., 20:55
На самом деле они по умолчанию показывают плоскую область, их не видно, потому что они перекрывают текст. Я должен парить над крошечнымx сделать полную кнопку видимой. Также пришлось добавить 5 пробелов в конце каждой подписи. Уггг :-)i.imgbox.com/YHlCTt13.png
 26 янв. 2015 г., 20:51
Работал для меня, хотя они работают совершенно иначе, чем ваша демоверсия. Прежде всего, они перекрывают лейбл для меня. Во-вторых, они отображаются только при наведении на вкладку. В-третьих, они показывают действительно очень маленькие. Использование XE7 в стиле Silver. Эти различия контролируются стилями?
 Cristian Vasuica10 мая 2012 г., 16:40
Привет, Родриго, я попытался реализовать хук с нестандартным стилем после того, как TLama предложил мне сделать это, но я перегружен этим. С помощью стилей vcl я не могу найти много документации, за исключением вашего блога. Я попробовал пару ваших примеров, но не могу справиться самостоятельно; Мне также нужен некоторый материал об обработке сообщений Windows. Я попытаюсь снова взглянуть на Google, и после некоторого времени чтения я попробую еще раз. Спасибо за советы, ребята!

Ваш ответ на вопрос