Задача сделать "открепление" вкладок в отдельное окно, просто потянув за них.
Вот, что на сегодня получилось (исходник) (работает в Win+Mac):
https://yadi.sk/d/kiqP9JFA3MjSyy
Зачем это надо.
Планируется каждую вкладку сделать максимально автономной, что бы при необходимости добавить функционал - мы просто подключали нужный нам пакет lpk (эх... dll-ку/dynlib бы цеплять... как там нынче в Lazarus с формами в динамических библиотеках?).
Притом хочется иметь возможность, при необходимости, "открепить" вкладку от главного окна и получить полноценное окно с заданными функциями.
Как мы делаем.
Создаем Form2, на него размещаем контролы.
При запуске приложения (или при нажатии кнопки) меняем родителя контрола (сперва хотел использовать InsertControl и вставить целиком окно, но возникли проблемы в MacOs X. Но менять родителя вышло даже удобнее) на один из табов главного окна.
- Код: Выделить всё
procedure TForm1.InsertForm2ToFotm1();// Отображаем элемент окна Form2 на контроле Form1
begin
if FindComponent('Form2') = nil then
Form2:=TForm2.Create(self) else Form2.Hide;
with Form2.Panel1 do
begin
with Form1 do begin
PageControl1.AddTabSheet;
PageControl1.Page[0].Caption:='Потяни меня';
Form2.Panel1.Parent:=PageControl1.Pages[0];
end;
Align:=alclient;
end;
end;
Если необходимо "открепить" дочерний контрол, то просто тянем его за заголовк таба и "вытягиваем" контрол в новое (родное) окно.
- Код: Выделить всё
procedure TForm1.PageControl1MouseDown(Sender: TObject; Button: TMouseButton; // ловим нажатие кнопки мыши в PageControl
Shift: TShiftState; X, Y: Integer);
begin
if Button=mbLeft then
begin
mX:=X;
mY:=Y;
mStateClick:=true;
end;
end;
procedure TForm1.PageControl1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
const
mXYdelta = 10;
begin
if mStateClick then
begin
PageControl1.cursor:=crDrag; // меняем курсор
if ((X<mX-mXYdelta) or (X>mX+mXYdelta) or (Y<mY-mXYdelta) or (Y>mY+mXYdelta)) then
begin
mX:=X;
mY:=Y;
mStateClick:=false;
DeleteForm2FromForm1(Form1.PageControl1.TabIndex);
end;
end else PageControl1.cursor:=crDefault;
end;
procedure TForm1.DeleteForm2FromForm1(TabIndex:Integer); // Удаляем элемент окна Form2 с контрола Form1 и отображаем в Form2 отдельно
begin
with Form2 do begin
// Hide;
Form1.PageControl1.Page[TabIndex].Destroy;
Form2.Panel1.Parent:=Form2;
WindowState:=wsNormal;
Show;
end;
end;
Открепили, но есть вопрос.
Как продолжить "тащить" уже новое окно?
То есть взяли, потащили - оторвали и продолжаем тащить? Подскажите решение, пожалуйста. Желательно кроссплатформенное.