I wish to add a context menu to the (just the) tab of a TPageControl as distinct from the tab area (e.g like Delphi does to offer file/page options). I know I can do this with TRzPageControl but how might it be possible with TPageControl please?
Asked
Active
Viewed 2,800 times
2 Answers
7
If you don't want to create a component, you can always use the OnContextPopup of your PageControl and depending on the Mouse position switch its PopupMenu.
Assume you have created 2 PopuMenus pmTabs ans pmPages, the following code will display the 1st when hitting the tabs area and the 2nd otherwise:
procedure TForm2.PageControl1ContextPopup(Sender: TObject; MousePos: TPoint;
var Handled: Boolean);
begin
with Sender as TPageControl do begin
if [htOnItem] * GetHitTestInfoAt(MousePos.X, MousePos.Y) <> [] then
PopupMenu := pmTabs
else
PopupMenu := pmPages;
end;
end;

Francesca
- 21,452
- 4
- 49
- 90
-
3`htOnItem in GetHitTestInfoAt(MousePos.X, MousePos.Y)` seems much more readable to me (and hopefully means the same :-)). – Uli Gerhardt Oct 05 '11 at 08:02
-
@Ulrich Gerhardt, I agree with you for this simple case, but I started with a more general approach using more than 1 hit area: `[htOnItem, htOnLabel] * GetHitTestInfoAt(MousePos.X, MousePos.Y) <> []` – Francesca Oct 06 '11 at 18:43
3
Many years ago, when I was still a kid (16 years old or something), I wrote this:
unit TabControlEx;
interface
uses
Windows, Menus, SysUtils, Classes, Controls, ComCtrls;
type
TTabControlEx = class(TCustomTabControl)
private
{ Private declarations }
protected
{ Protected declarations }
FPopupMenu: TPopupMenu;
FPopupActivatesTab: boolean;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
public
{ Public declarations }
published
{ Published declarations }
property Align;
property Anchors;
property BiDiMode;
property Constraints;
property Cursor;
property DockSite;
property DragCursor;
property DragKind;
property DragMode;
property Enabled;
property Font;
property Height;
property Hint;
property HotTrack;
property Images;
property Left;
property MultiLine;
property MultiSelect;
property OwnerDraw;
property ParentBiDiMode;
property ParentFont;
property ParentShowHint;
property PopupActivatesTab: boolean read FPopupActivatesTab write FPopupActivatesTab;
property PopupMenu;
property RaggedRight;
property ScrollOpposite;
property ShowHint;
property Style;
property TabHeight;
property TabIndex;
property TabOrder;
property TabPopupMenu: TPopupMenu read FPopupMenu write FPopupmenu;
property TabPosition;
property Tabs;
property TabStop;
property TabWidth;
property Top;
property Visible;
property Width;
property OnChange;
property OnChanging;
property OnContextPopup;
property OnDockDrop;
property OnDockOver;
property OnDragDrop;
property OnDragOver;
property OnEndDrag;
property OnEndDock;
property OnDrawTab;
property OnEnter;
property OnExit;
property OnGetImageIndex;
property OnGetSiteInfo;
property OnMouseDown;
property OnMouseMove;
property OnMouseUp;
property OnResize;
property OnStartDrag;
property OnStartDock;
property OnUnDock;
end;
procedure Register;
implementation
{$R *.dcr}
procedure TTabControlEx.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
CursorPos: TPoint;
begin
inherited MouseDown(Button, Shift, X, Y);
if (Button = mbRight) and (IndexOfTabAt(X, Y) <> -1) then
if Assigned(TabPopupMenu) then
begin
if FPopupActivatesTab and (TabIndex <> IndexOfTabAt(X, Y)) then
begin
TabIndex := IndexOfTabAt(X, Y);
if Assigned(OnChange) then OnChange(self);
end;
GetCursorPos(CursorPos);
with CursorPos do
FPopupMenu.Popup(X, Y);
end;
end;
procedure Register;
begin
RegisterComponents('Rejbrand', [TTabControlEx]);
end;
end.
It might still work.

Andreas Rejbrand
- 105,602
- 8
- 282
- 384
-
You might save some nanojoule of electric energy per day or so by saving `IndexOfTabAt(X, Y)` in a local variable... – Andreas Rejbrand Oct 04 '11 at 17:11
-
Of course, you can do the exact same thing with a page control (and not a tab control). – Andreas Rejbrand Oct 04 '11 at 17:14