Форум программистов, компьютерный форум, киберфорум
Delphi для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.82/11: Рейтинг темы: голосов - 11, средняя оценка - 4.82
134 / 133 / 22
Регистрация: 29.08.2012
Сообщений: 353
1

Изменение размера формы fsNone

24.05.2013, 23:12. Показов 2297. Ответов 10
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Доброго времени суток.
Уважаемые, помогите решить задачку.
пытаюсь реализовать по своему интерфейс аля фотошоп с отклеивающимися панелями(в моем случае фрэймы), сам процесс отклеивания реализовал через отдельную форму(все фрэймы расположены на главной форме, в случае "отклеивания" для каждой есть отдельная пустая форма, formstyle=fsNone, заголовок и "системные кнопки" отрисованы через панель со скинами, непосредственно на фрэйме), перемещение формы за панель честно спер в интернетах, а вот изминение размеров этой формы сделать не могу, пока в общем случае пытаюсь "придумать сам", через mouse(Down|Move|Up) при таком вот коде:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
var x_size,y_size:integer;
f_res:boolean;
...
...
procedure TFr_Close.sStatusBar1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);//нажимаем на статус бар
begin
if self.Parent=Fm_Close then //если фрэйм на отстыкованной форме
   begin
     x_size:=Fm_Close.Width;
     y_size:=Fm_Close.Height;
     F_res:=true;//запомнили размеры, разрешили изменять
   end;
end;
 
procedure TFr_Close.sStatusBar1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);//тянем
begin
if (self.Parent=Fm_Close) and F_res=true then//фрэйм отстыкован и можно изменять
   begin
     Fm_Close.Width:=x;
     Fm_Close.Height:=y;//для наглядности чтобы видеть как изменяются размеры
     x_size:=x;
     y_size:=y;//без наглядности, запоминаем координаты мыши
     //Fm_Close.Canvas.Rectangle(Fm_Close.Top,Fm_Close.Left,x_size,y_size);
   end;
end;
 
procedure TFr_Close.sStatusBar1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);//отпускаем
begin
if (self.Parent=Fm_Close)then//если отстыкован
   begin
     Fm_Close.Width:=x_size;
     Fm_Close.Height:=y_size;
     f_res:=false;//устанавливаем размер, запрещаем изменять
   end;
end;
{Fr_Close --> Frame, Fm_Close --> Form}
форма ведет себя странно, при микроизминениях может сложится в точку или в строку, если убираю из TFr_Close.sStatusBar1MouseMove присвоение координат непосредственно к размерам - форма вообще пропадает после отпускания мыши, немогу понять где моя логика сломалась

а также подскажите пожалуйста по вытекающему вопросу, как реализовать "рамку формы", чтобы она отрисовывалась при изминении размера, если размеры назначать непосредственно форме - сильно мерцает.

заранее благодарен.
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
24.05.2013, 23:12
Ответы с готовыми решениями:

Изменение размера формы
Нужно Предоставить пользователю возможность изменять размер формы, расположение объектов на форме...

Изменение размера формы
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); var...

Изменение размера формы
Создано приложение с большим числом кликабельных графических элементов. Не удобно отображается на...

Изменение размера формы
Извините за тупой вопрос, но всё никак не могу понять как изменить высоту формы сверху ( не снизу...

10
134 / 133 / 22
Регистрация: 29.08.2012
Сообщений: 353
25.05.2013, 11:37  [ТС] 2
Добавил исходник на чистом проекте, и я перепутал у формы BorderStyle=bsNone
Вложения
Тип файла: zip TestFrame.zip (261.1 Кб, 9 просмотров)
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
32835 / 21172 / 8148
Регистрация: 22.10.2011
Сообщений: 36,431
Записей в блоге: 8
25.05.2013, 12:05 3
Почему выбран TFrame, а не TForm, которой можно сделать Dock/UnDock, и с которой всё делается гораздо проще?

А уж если положить на главную форму TDockTabSet, то вообще получается вот такая история:
Изменение размера формы fsNone

Вытягиваешь за заголовок:
Изменение размера формы fsNone
1
134 / 133 / 22
Регистрация: 29.08.2012
Сообщений: 353
25.05.2013, 12:22  [ТС] 4
я пробовал с формами, у меня постоянно наровят вылезти артефакты в виде заголовка формы, решается путем ручной отрисовки как и сейчас с фрэймом, при отстыковке выхватывал эксепшены, сейчас уже не вспомню какие, но побороть не смог, стыковал так
Delphi
1
FmWin1.ManualDock(MainForm.sPanel2);
, отстыковывать перестал после выхватывания эксепшенов, в итоге просто прятал активную форму и очищал ее(очень много дин.объектов). сейчас вернулся к программе решил переработать немного, с чистой формой и фреймом мне показалось немного поприятнее.(или проще)
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
32835 / 21172 / 8148
Регистрация: 22.10.2011
Сообщений: 36,431
Записей в блоге: 8
25.05.2013, 12:30 5
Цитата Сообщение от Ev1l Посмотреть сообщение
с чистой формой и фреймом мне показалось немного поприятнее.(или проще)
Вот ты и получил "приятнее" в виде изменения размера фрейма

Как хочешь, я всегда делаю с формами, если и вылазят артефакты - то только по моей собственной вине, пишешь правильно - они пропадают... Доставляй себе "приятное" дальше. Это не последнее, с чем у тебя будут проблемы на фреймах.

Добавлено через 2 минуты
Цитата Сообщение от Ev1l Посмотреть сообщение
MainForm.sPanel2
А AlphaSkins тут вообще ни к селу ни к городу, у тебя ж новая версия Дельфи? Project->Options->Application->Appearance зайди...
0
134 / 133 / 22
Регистрация: 29.08.2012
Сообщений: 353
25.05.2013, 12:47  [ТС] 6
Цитата Сообщение от UI Посмотреть сообщение
А уж если положить на главную форму TDockTabSet, то вообще получается вот такая история:
А вот слона то я и не заметил, спасибо, пойду читать.

Добавлено через 1 минуту
2009, нет Appearance
0
134 / 133 / 22
Регистрация: 29.08.2012
Сообщений: 353
29.05.2013, 00:40  [ТС] 7
UI, если не сложно, подскажи пожалуйста по DockTabSet, в инете не могу ничего путного найти, пытаюсь разобраться, но не все получается, вот мой код:
Кликните здесь для просмотра всего текста
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Buttons, Tabs, DockTabSet, ExtCtrls;
 
type
  TForm1 = class(TForm)
    BitBtn1: TBitBtn;
    Panel2: TPanel;
    DockTabSet2: TDockTabSet;
    Panel3: TPanel;
    procedure BitBtn1Click(Sender: TObject);
    procedure Panel2DockOver(Sender: TObject; Source: TDragDockObject; X,
      Y: Integer; State: TDragState; var Accept: Boolean);
    procedure Panel2UnDock(Sender: TObject; Client: TControl;
      NewTarget: TWinControl; var Allow: Boolean);
    procedure DockTabSet2TabAdded(Sender: TObject);
    procedure DockTabSet2TabRemoved(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
var
  Form1: TForm1;
 
implementation
 
uses Unit2;
 
{$R *.dfm}
 
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
form2.ManualDock(DockTabSet2);
DockTabSet2.ShowDockClient(form2);
form2.show;
end;
 
procedure TForm1.DockTabSet2TabAdded(Sender: TObject);
begin
Panel3.Width:=150;
if DockTabSet2.Visible=false then DockTabSet2.Show;
DockTabSet2.TabIndex:=0;//пытаюсь так отобразить только что пристыкованную форму
end;
 
procedure TForm1.DockTabSet2TabRemoved(Sender: TObject);
begin
if Panel2.DockClientCount=0 then Panel3.Width:=0;
if DockTabSet2.Tabs.Count=0 then DockTabSet2.Hide;
end;
 
 
procedure TForm1.Panel2DockOver(Sender: TObject; Source: TDragDockObject; X,
  Y: Integer; State: TDragState; var Accept: Boolean);
begin
Panel3.Width:=150;
end;
 
procedure TForm1.Panel2UnDock(Sender: TObject; Client: TControl;
  NewTarget: TWinControl; var Allow: Boolean);
begin
if panel2.DockClientCount=0  then Panel3.Width:=0;
end;
 
end.

на первой форме стот панель(Panel3), на ней DockTabSet2(alTop), под ней, там же на панели 3 - Panel2(alClient, она же DestinationDockSite)
у меня следующие неприятности:
1 перемещение формы как-то очень сильно тормозит, DoubleBuffered не помогает.
2 как правильно отобразить содержимое таба, при стыковке форма сворачивается в таб, а вот как развернуть програмно не понимаю
3 мелочи, впринципе видимо где то забыл свернуть панель, и сам разобраться смогу, но переодически панель остается видимой.
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
32835 / 21172 / 8148
Регистрация: 22.10.2011
Сообщений: 36,431
Записей в блоге: 8
29.05.2013, 11:07 8
Лучший ответ Сообщение было отмечено volvo как решение

Решение

Ev1l, значит, так... Рассказываю все по порядку, может, и еще кому пригодится...

Для начала - с основной формой, той, на которую будут пристыковываться другие.

Кликните здесь для просмотра всего текста
1. Кладем на форму TDockTabSet, и две панели. Первая, которую я назвал DockPanel - это именно та панель, с которой будет работать TDockTabSet, то есть, на ней и будут отображаться пристыкованные формы. Вторая - названная DockPositionPanel - расположена на первой, и изначально невидима. У этой панели другая задача: она будет в момент протягивания формы над DockPanel показывать, как будет пристыковываться форма, сверху, снизу, слева или справа, поэтому ее цвет надо выставить в отличный от дефолтного, чтобы это было видно.

Разумеется, настраиваем компоненты:
DockTabset.DestinationDockSite = DockPanel
DockTabset.TabPosition = tpLeft
DockTabset.Style = tsModernPopout
DockTabset.Visible = false // Пока нет пристыкованных форм, нечего и показывать...

2. Стандартная обработка OnDockOver/OnDockDrop для DockPanel:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
procedure TForm1.DockPanelDockDrop(Sender: TObject; Source: TDragDockObject; X,
  Y: Integer);
var i, max_width : Integer;
begin
  // Тут подстраиваем ширину панели под самую широкую из пристыкованных форм
  if DockPanel.DockClientCount = 0 then DockPanel.Width := 3
  else
  begin
    max_width := 0;
    for i := 0 to Pred(DockPanel.DockClientCount) do
    begin
      if DockPanel.DockClients[i].UndockWidth > max_width then
        max_width := DockPanel.DockClients[i].UndockWidth;
    end;
    DockPanel.Width := max_width;
  end;
end;
 
procedure TForm1.DockPanelDockOver(Sender: TObject; Source: TDragDockObject; X,
  Y: Integer; State: TDragState; var Accept: Boolean);
var TL, BR : TPoint;
begin
  // А вот тут - показываем, перемещая DockPositionPanel, где именно будет располагаться
  // вновь пристыкованная форма
  DockPositionPanel.Visible := State <> dsDragLeave;
  if State = dsDragLeave then DockPanel.Repaint;
 
  TL := DockPanel.ScreenToClient(Point(Source.DockRect.Left, Source.DockRect.Top));
  BR := DockPanel.ScreenToClient(Point(Source.DockRect.Right, Source.DockRect.Bottom));
 
  DockPositionPanel.BoundsRect := Rect(TL, BR);
  DockPositionPanel.BringToFront;
end;
3. Ну, и завершаем с этой формой. По событию добавления/удаления таба изменяем видимость DockTabSet, чтобы, когда он пустой, не мозолил глаза:
procedure TForm1.DockTabSet1TabAdded(Sender: TObject);
Delphi
1
2
3
4
5
6
7
8
begin
  DockTabSet1.Visible := True;
end;
 
procedure TForm1.DockTabSet1TabRemoved(Sender: TObject);
begin
  DockTabSet1.Visible := DockTabSet1.Tabs.Count > 0;
end;


Теперь переходим ко второй форме, которую будем стыковать

Кликните здесь для просмотра всего текста
1. Настраиваем
DragKind = dkDock
DragMode = dmAutomatic

2. Для того, чтобы сделать красивое перемещение формы, воспользуемся специальным классом: TDragDockObjectEx. Унаследуемся от него, и переопределим некоторые методы на свой вкус:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
type
  TMyDragDock = class(TDragDockObjectEx)
  private
    FDragImageList : TDragImageList;
  protected
    function GetDragImages: TDragImageList; override;
  public
    constructor Create(AControl : TControl); override;
    destructor Destroy; override;
  end;
 
constructor TMyDragDock.Create(AControl : TControl);
var
  bmp : TBitmap;
begin
  // При создании объекта создадим ImageList, по размеру
  // хранимых изображений совпадающий с формой ...
  inherited Create(AControl);
  FDragImageList := TDragImageList.CreateSize(AControl.Width, AControl.Height);
  FDragImageList.Masked := true;
 
  FDragImageList.Clear;
  bmp := TBitmap.Create;
  try
    bmp.SetSize(AControl.Width, AControl.Height);
    bmp.Canvas.Brush.Style := bsSolid;
    bmp.Canvas.Brush.Color := clBlue;
    bmp.Canvas.FillRect(bmp.Canvas.ClipRect);
 
    // и занесем в него закрашенный цветом clBlue битмап. Теперь, при перетягивании
    // объекта, будет перетягиваться как раз этот самый битмап
 
    FDragImageList.Add(bmp, nil);
    Control.Tag := Integer(FDragImageList);
  finally
    bmp.Free;
  end;
end;
 
// Не забываем удалить ImageList
destructor TMyDragDock.Destroy;
begin
  FDragImageList.Free;
end;
 
// По требованию - возвращаем ImageList, система разбирается, когда ей нужно
// вытащить оттуда изображения, и отобразить их
function TMyDragDock.GetDragImages: TDragImageList;
begin
  Result := FDragImageList;
end;
3. Теперь, собственно, к нашей форме. Чтобы этот TMyDragDock заработал, его надо создать. Делаем это по событию OnStartDock, то есть, когда пользователь начинает тащить форму:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
procedure TForm2.FormStartDock(Sender: TObject;
  var DragObject: TDragDockObject);
var pos : TPoint;
begin
  DragObject := TMyDragDock.Create(Self); // Вот оно, основное действие !!!
  GetCursorPos(pos);
  Dec(pos.x, Self.Left);
  Dec(pos.y, Self.Top);
 
  // Ну, и выставляем DragHotspot, то есть, точку, за которую тянется изображение,
  // чтобы синий прямоугольник точно закрывал форму, а не был смещен относительно нее
  (TDragImageList(DragObject.Control.Tag)).DragHotspot := pos;
end;
4. Осталось сделать еще 2 вещи: обработать прекращение протягивания формы (если этого не сделать, то синий прямоугольник не будет удален, и останется висеть на экране, а кому это нужно?), и отменить дефолтную прорисовку (это самое перемещение контура формы, которое как раз и тормозит, да еще с мерцанием). Это делается вот так:

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
type
  TForm2 = class(TForm)
  // ...
  private
    { Private declarations }
  public
    { Public declarations }
  protected
    // Переопределяем эти 2 метода
    procedure EraseDragDockImage(DragDockObject : TDragDockObject); override;
    procedure DefaultDockImage(DragDockObject: TDragDockObject; Erase: Boolean); override;
  end;
 
// ...
 
// Ну, и реализация:
procedure TForm2.EraseDragDockImage(DragDockObject : TDragDockObject);
begin
  if DragDockObject.Cancelling then // Отмена "протягивания"?
      (TDragImageList(DragDockObject.Control.Tag)).EndDrag; // Значит, завершаем...
end;
 
// Здесь ничего делать не надо, оставляем реализацию пустой, это отменит дефолтную обработку
procedure TForm2.DefaultDockImage(DragDockObject: TDragDockObject; Erase: Boolean);
begin
  //
end;
5. Ну, и еще одна мелочь: при закрытии формы Action выставляем в acFree, чтобы она удалилась, а не просто была скрыта:
Delphi
1
2
3
4
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;
end;


Всё, получаем приятное глазу перетягивание/пристыковку формы. На всякий случай присоединил еще и проект (создан на XE2), если вдруг забыл здесь упомянуть о каком-то свойстве, и из-за этого программа будет работать не так, как ожидается - можно посмотреть в исходниках.

P.S. У этого проекта осталась одна проблема: при отстыковке формы прямоугольник уходит влево, в не отображается там, где находится мышь. Чуть позже попробую избавиться от этого...
Вложения
Тип файла: zip test_dock_2.zip (725.5 Кб, 28 просмотров)
2
134 / 133 / 22
Регистрация: 29.08.2012
Сообщений: 353
29.05.2013, 11:30  [ТС] 9
Огромное спасибо.
У меня остался только один вопрос по этой теме, как перехватить управление кнопкой "скрепка"(допустим, я хочу чтобы в таб сет она не пряталась, а сразу отстыковывалась на текущее положение, и возврашалась в исходноеное состояние /*кнопка в состояние прилеплена*/ когда снова пристыковывается на панель)?
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
32835 / 21172 / 8148
Регистрация: 22.10.2011
Сообщений: 36,431
Записей в блоге: 8
29.05.2013, 12:42 10
У тебя нет возможности управлять этой кнопкой. Вся работа с pin-button делается автоматически.
1
134 / 133 / 22
Регистрация: 29.08.2012
Сообщений: 353
29.05.2013, 12:50  [ТС] 11
Ясно, спасибо.
0
29.05.2013, 12:50
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
29.05.2013, 12:50
Помогаю со студенческими работами здесь

Изменение размера\положения кнопок при resize формы
Всем привет! На форме 9 кнопок, 6 одного и 3 другого размера, пытаюсь изменять их размер\положение...

Изменение размера формы при переходе на другую вкладку
Здравствуйте, такой вопрос. У меня есть компонент на форме (PageControl). И несколько вкладок. Так...

Изменение размера формы под пространство занимаемое компонентами на ней.
Привет всем! У меня есть форма в которой динамически создаються множество компонентов, я бы хотел...

Изменение размера формы
Скажите пожалуйста, как програмно уменьшить размер формы? По нажатию на кнопку (Butto1) размер...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru