Comment puis-je implémenter un bouton de fermeture pour une feuille de ttabshets d'un tpagecontrol comme Firefox? P>
edit: strong>
Version Delphi: Delphi 2010
OS: Windows XP et UP P>
4 Réponses :
Maintenant avec prise en charge de thème (Inclure Windows, UXTHEME, THÈMES CODE> Unités)! type
TFormMain = class(TForm)
{...}
private
FCloseButtonsRect: array of TRect;
FCloseButtonMouseDownIndex: Integer;
FCloseButtonShowPushed: Boolean;
{...}
end;
{...}
procedure TFormMain.FormCreate(Sender: TObject);
var
I: Integer;
begin
PageControlCloseButton.TabWidth := 150;
PageControlCloseButton.OwnerDraw := True;
//should be done on every change of the page count
SetLength(FCloseButtonsRect, PageControlCloseButton.PageCount);
FCloseButtonMouseDownIndex := -1;
for I := 0 to Length(FCloseButtonsRect) - 1 do
begin
FCloseButtonsRect[I] := Rect(0, 0, 0, 0);
end;
end;
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;
Windows.DrawFrameControl(PageControl.Canvas.Handle,
FCloseButtonsRect[TabIndex], DFC_CAPTION, CloseBtnDrawState);
end
else
begin
Dec(FCloseButtonsRect[TabIndex].Left);
if (FCloseButtonMouseDownIndex = TabIndex) and FCloseButtonShowPushed then
CloseBtnDrawDetails := ThemeServices.GetElementDetails(twCloseButtonPushed)
else
CloseBtnDrawDetails := ThemeServices.GetElementDetails(twCloseButtonNormal);
ThemeServices.DrawElement(PageControl.Canvas.Handle, CloseBtnDrawDetails,
FCloseButtonsRect[TabIndex]);
end;
end;
end;
procedure TFormMain.PageControlCloseButtonMouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
I: Integer;
PageControl: TPageControl;
begin
PageControl := Sender as TPageControl;
if Button = mbLeft then
begin
for I := 0 to Length(FCloseButtonsRect) - 1 do
begin
if PtInRect(FCloseButtonsRect[I], Point(X, Y)) then
begin
FCloseButtonMouseDownIndex := I;
FCloseButtonShowPushed := True;
PageControl.Repaint;
end;
end;
end;
end;
procedure TFormMain.PageControlCloseButtonMouseMove(Sender: TObject;
Shift: TShiftState; X, Y: Integer);
var
PageControl: TPageControl;
Inside: Boolean;
begin
PageControl := Sender as TPageControl;
if (ssLeft in Shift) and (FCloseButtonMouseDownIndex >= 0) then
begin
Inside := PtInRect(FCloseButtonsRect[FCloseButtonMouseDownIndex], Point(X, Y));
if FCloseButtonShowPushed <> Inside then
begin
FCloseButtonShowPushed := Inside;
PageControl.Repaint;
end;
end;
end;
procedure TFormMain.PageControlCloseButtonMouseLeave(Sender: TObject);
var
PageControl: TPageControl;
begin
PageControl := Sender as TPageControl;
FCloseButtonShowPushed := False;
PageControl.Repaint;
end;
procedure TFormMain.PageControlCloseButtonMouseUp(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
PageControl: TPageControl;
begin
PageControl := Sender as TPageControl;
if (Button = mbLeft) and (FCloseButtonMouseDownIndex >= 0) then
begin
if PtInRect(FCloseButtonsRect[FCloseButtonMouseDownIndex], Point(X, Y)) then
begin
ShowMessage('Button ' + IntToStr(FCloseButtonMouseDownIndex + 1) + ' pressed!');
FCloseButtonMouseDownIndex := -1;
PageControl.Repaint;
end;
end;
end;
Semble très gentil. La capture d'écran est une bonne touche! Malheureusement, il ne semble que convient uniquement à Windows 2000 ou à XP non thématique? Vista / 7. Avez-vous une version qui utilise l'API sur le thème?
J'ai testé votre code et ça fonctionne bien. Donc, je sélectionne votre code comme réponse. Mais à cause des autres fidutres, j'ai besoin de décider d'utiliser un TJVTabar de Jedi JVCl avec un littel modifié TJVTABBarXPPetager.
Quelle est la fonction inrange? Je suppose que c'est une fonction spécifique D2010 que je n'ai pas dans D2009. Y a-t-il une fonction similaire dans D2009 Avaisialble?
Cela fonctionne bien sur Delphi 2007 pour utiliser la fonction InRange, vous devez ajouter l'unité "Math" à la section Utilisations du formulaire.
Ne montre pas les images d'onglet Contrôle de la page. A besoin de plus de travail.
Ce que j'ai fait dans le passé, il suffit de mettre un TBITBTN avec un graphique dans le coin supérieur droit du TPAGECONTROL. L'astuce I Le parent du TBITBTN est identique à la tpagecontrol, de sorte que ce n'est pas réellement sur l'une des feuilles de tabulation. Ensuite, dans le clic même pour ce bouton:
PageControl1.ActivePage.Free;
C'est souvent une bonne idée de la mettre en œuvre vous-même, car les autres réponses ont suggéré. Juste au cas où vous utilisez déjà Composants RATIAD , cependant, cette fonctionnalité est supportée "hors de la boîte". Il suffit de définir [juste un client heureux] p> trzpagecontrol.showclosebuttononactivetab: = true code> et gérer le osez "/ code> événement". Le composant s'occupe de la mise en place d'une variété de dispositions / orientations / formes / couleurs / couleurs. p>
J'ai changé un peu cet exemple:
- Création de la classe TCloTabsheet
- cette classe a la propriété surClose: TnotifyEvent, qui sera appelé si attribué
- Si tabsheet of of tpagecontrol n'est pas cette classe, il n'y a pas de bouton de fermeture
- S'il est alors le bouton montré. Lorsque vous appuyez sur le bouton Fermer, il appelle l'application
- Maintenant, vous n'avez pas besoin de contrôler le tableau FCLOSEBUTONSRECT, car ces rects stockés à TClosetabsheet
Quel style voulez-vous dire? Celui où chaque onglet a son propre bouton, ou le style où il y a un bouton à l'extrême droite qui s'applique à l'onglet est actuellement actif?
@Rob OUI, avec un bouton de fermeture sur chaque onglet