Язык программирования Delphi. Docking - перемещение компонентов:
Почему-то меня очень часто просят рассказать, как можно добиться такого эффекта как у ToolBar-ов в M$ Office. Для большей ясности - это когда палитру с кнопками можно оторвать от окна и прилепить в другое место или вообще превратить в отдельное окно. Лично мне казался этот материал очень простым. Но так как таких писем стало уже очень много, я решил написать статью, чтобы не объяснять каждому в отдельности.
Рис 1. Пример формы
Для того, чтобы TToolBar можно было перемещать, достаточно установить в нём свойство
DragKind в dkDock. Вот и всё. Но главная проблема не в этом. Самое сложное здесь - это сохранить положение TToolBar после выхода из проги и восстановить его при запуске. Для примера я написал маленькую прогу, которую ты должен доделать до полноценной.
Для демонстрации мне понадобилась кнопка, по нажатию которой будет выводится положение TToolBar:
procedure TForm1.Button1Click(Sender: TObject);
var
r:TRect;
begin
if ToolBar1.HostDockSite<>ControlBar1 then
begin
GetWindowRect(ToolBar1.Handle, R);
Application.MessageBox(PChar(IntToStr(r.Left)+'--'+IntToStr(r.Top)),
'MM',IDOK);
end;
end;
В первой строке я проверяю, лежит ли ToolBar1 на ControlBar1 с помощью (ToolBar1.HostDockSite<>ControlBar1). Если он лежит, то получить положение ToolBar1 очень просто. Для этого можно узнать всего лишь ToolBar1.Left и ToolBar1.Top.
Если ToolBar1 не лежит на ControlBar1 (ToolBar1 выглядит как отдельное окно), то задача усложняется. Тебе придётся вызывать GetWindowRect, чтобы получить реальное положение ToolBar1 на экране. В качестве первого параметра ты должен передать указатель на ToolBar1, а второй - это переменная типа TRect в которую запишется реальное положение окна. Для удобства я вывожу эти знчения в окне сообщения Application.MessageBox.
Всё это я делаю для наглядности. Теперь ты можешь запустить прогу и переместить ToolBar1 по экрану. Каждый раз, когда ты будешь нажимать кнопку, программа будет выводить окно и показывать тебе реальное положение ToolBar1.
По событию OnShow я написал:
procedure TForm1.FormShow(Sender: TObject);
begin
ToolBar1.ManualDock(nil,nil,alNone);
ToolBar1.ManualFloat(Bounds(100, 500, ToolBar1.UndockWidth,
ToolBar1.UndockHeight));
end;
ToolBar1.ManualDock заставляет переместится ToolBar1 на новый компонент. В качестве первого параметра указывается указатель на компонент или окно, к которому мы хотим прилепить ToolBar1. Я хочу, чтобы после загрузки ToolBar1 превратился в отдельное окно, поэтому я указываю nil. Второй параметр можешь ставить nil. Он означает компонент внутри компонента указанного в качестве первого параметра, на который мы хотим поместить ToolBar1. Я указал nil. Третий параметр - выравнивание.
С помощью ToolBar1.ManualFloat я просто двигаю ToolBar1 внутри нового компонента. У меня новый компонент nil, т.е. окно, поэтому я двигаю ToolBar1 по окну. Может не совсем понятно? Попробуй запустить пример и поиграть с ним, тогда всё встанет на свои места.
И ещё ToolBar1.UndockWidth и ToolBar1.UndockHeight возвращают размер ToolBar1, когда он выглядит как окно, а не лежит на ControlBar1.
Когда ты будешь использовать это в своей проге для сохранения положения ToolBar1, тебе надо будет написать примерно следующее по событию OnClose:
var
r:TRect;
begin
if ToolBar1.HostDockSite<>ControlBar1 then
begin
GetWindowRect(ToolBar1.Handle, R);
Здесь надо сохранить в реестре R.Left и R.Top.
А также признак, что ToolBar1 не лежит на ControlBar1
end
else
begin
Здесь надо сохранить в реестре ToolBar1.Left и ToolBar1.Top.
А также признак, что ToolBar1 лежит на ControlBar1
end;
end;
На запуск программы ты должен написать примерно следующее:
procedure TForm1.FormShow(Sender: TObject);
begin
Прочитать положение ToolBar1. ControlBar1 то
Begin
ToolBar1.Left:=Сохранённая левая позиция
ToolBar1.Topt:=Сохранённая верхняя позиция
End;
Иначе
begin
ToolBar1.ManualDock(nil,nil,alNone);
ToolBar1.ManualFloat(Bounds(Сохранённая левая позиция,
Сохранённая правая позиция, ToolBar1.UndockWidth,
ToolBar1.UndockHeight));
End;
end;
Как видишь, подводные булыжники есть. Но всё же ничего сильно сложного нет.
Рис 2. Меню
Теперь мы сделаем менюшку в стиле M$. Для этого нужно поставить ещё один ToolBar и установим его свойство ShowCaption в true.Создадим на нём две кнопки и назовём их File и Edit . Теперь установим компонент MainMenu и сделаем его таким как на рисунке 2. Меню Not visible сделаем невидимым (Visible=false), в этом случае всё меню будет подключено к форме но будет не видно. Для чего я это делаю, ведь можно было использовать PopupMenu? А потому что при использовании PopupMenu приходится мучится с клавишами быстрого вызова, а в моём способе они подключаются автоматически вместе с главным меню.
Примечание!!! Чтобы создать подменю для меню File, нужно щёлкнуть по нём правой кнопкой и выбрать Create Submenu или нажать CTRL+Стрелка в право.
Теперь кнопке File в свойстве MenuItem ставим File1 (имя пункта меню), а кнопке Edit ставим Edit1. И на последок обеим кнопкам нужно установить свойство Grouped в true.