Link to home
Start Free TrialLog in
Avatar of WinRat
WinRatFlag for South Africa

asked on

Add dragable tabs to the Delphi TPageView component

Hello Delphi Experts,

Delphi 6's Editor Window has tabs which can be dragged so you can have a different order.
e.g. if you have Unit1 Unit2 Unit3 you can change it to Unit3 Unit1 Unit2
(useful if you have a project with many files and you want some of them to be always visible)

However the TPageView component in D5 and D6 does not Ā have the same feature. Can some Delphi Expert create a new class based on the existing TPageView that does allow dragable tabs (with a property to enable it)? Can be for either D6 or D5. if I haven't explained clearly enough please ask.

Thank you.
Avatar of Geert G
Geert G
Flag of Belgium image

i didn't create a component,

just set TPageControl, dragmode to dmManual and add these events
procedure TForm1.PageControl1DragOver(Sender, Source: TObject; X,
  Y: Integer; State: TDragState; var Accept: Boolean);
var currTab, TargetTab: integer;
  pc: TPageControl;
begin
  Accept := Assigned(Sender) and Assigned(Source) and (Sender = Source) and (Sender is TPageControl);
  if Accept then
  begin
    pc := Sender as TPageControl;
    TargetTab := pc.IndexOfTabAt(X, Y);
    CurrTab := pc.Tag;
    if not ((TargetTab <> -1) and (TargetTab <> CurrTab)) then
      Accept := False;
  end;
end;
 
procedure TForm1.PageControl1DragDrop(Sender, Source: TObject; X,
  Y: Integer);
var
  currTab, TargetTab: integer;
  pc: TPageControl;
begin
  if Assigned(Sender) and Assigned(Source) and (Sender = Source) and (Sender is TPageControl) then
  begin
    pc := Sender as TPageControl;
    TargetTab := pc.IndexOfTabAt(X, Y);
    CurrTab := pc.Tag;
    if (CurrTab <> -1) and (TargetTab <> -1) and (TargetTab <> CurrTab) then
    begin
      pc.Pages[CurrTab].PageIndex := TargetTab;
    end;
  end;
end;
 
procedure TForm1.PageControl1StartDrag(Sender: TObject;
  var DragObject: TDragObject);
var pc: TPageControl;
  p: TPoint;
begin
  if Assigned(Sender) and (Sender is TPageControl) then
  begin
    pc := Sender as TPageControl;
    p := pc.ScreenToClient(Mouse.CursorPos);
    pc.Tag := pc.IndexOfTabAt(p.X, p.Y);
  end;
end;

Open in new window

it does use the Tag of the PageControl
you may need to set it to a variable if you use the Tag yourself !
dunno if this works in D5, i did this in D7
oops the click doesn't work anymore (changing tabs)
the DragMode had to be set to dmAutomatic, not dmManual

funny stuff this, i did a workaround for setting the tab order, or changing the tabs with a checkbox
but that's silly, i'll have a deeper look
Avatar of WinRat

ASKER

Geert_Gruwez:

I tried your solution in D5 and as you said you have to set DragMode to Auto and the tabs drag as wanted - but then you can't select different tabs. Stays on the first default one selected. good luck - half-way there!

that's allways the problem ... it's allways the second half !
ASKER CERTIFIED SOLUTION
Avatar of Geert G
Geert G
Flag of Belgium image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
forgot to say, set PageControl DragMode = dmManual
Avatar of WinRat

ASKER

Geert_Gruwez:
I got it to work already. Drag mode defaults to Manual.
Going to award you the points since you answered my question perfectly! Good work and fast!

Having used it I see some aspect that could be improved. If you have many pages and several of the tabs are not visible i.e.you need to use the scroll buttons to get to them, would it be feasible to have the following behaviour:

You want to drag hidden tab 6 to be the first one.
You scroll right to get one of the hidden tabs, then drag it to the left when you get to the end of the pagecontrol tab 1 you keep dragging and the tabs scroll right automatically until you get to Tab 1.
Same thing in the other direction, i.e. dragging tab1 to be the last one.
Not sure if i explained this well but if you try it you will see what I mean.

If you think it is possible I will submit as a new question as an enhancement to this solution.

Thanks so much!
Have to go home now so won't be on-line until later this evening.
Avatar of WinRat

ASKER

I didn't know you could redefine a component within a unit like that, even after you have dropped it on the form. Clever. Please see extra comments.
Thanks again. Sure will be of general interest.
PS: Did you see my related question about Delphi 5's Editor Window tabs? Didn't get a way of adding to D5. D6 has it already.
https://www.experts-exchange.com/questions/24161533/Dragable-page-TABS-for-Delphi-5's-File-Editor.html