Многие практикующие Delphi-программисты знают, что у стандартного TSplitter’а есть ряд недостатков (т.е. багов, если сказать откровенно). В попытках борьбы с ошибками стандартного TSplitter’а, а также желая “прикрутить” к сплиттеру кнопку (для скрытия/отображения связанной панели), я в своё время перепробовал много компонент (доступных для бесплатного скачивания), но так ни на чём конкретно и не остановился: все варианты были чем-то не тем, что нужно было мне. В итоге я решил написать свой компонент.
За основу компонента я взял обычный TSplitter (copy/paste). Первое что я сделал - поменял у него родительский класс (TGraphicControl заменил на TCustomControl), что позволило сделать нормальную обработку клавиатуры (Escape-клавиша) и мыши (без хаков и подменой обработчиков у активного контрола). Во-вторых ввёл понятие AlignControl – связанный со сплиттером компонент (у TSplitter этот компонент определяется в run-time и это иногда приводит к тому, что сплиттер теряет привязку к компоненту). Затем я добавил кнопку (алгоритм прорисовки которой я позаимствовал у другого сплиттера, к сожалению уже не помню какого именно). Ну, и на последок, компонент обзавёлся способностью связываться с Action’ами.
Итак, предлагаю Вашему вниманию VCL компонент: TdnSplitter. Это ещё один клон сплиттера, но у него есть отличительные особенности. Самая главная – TdnSplitter не является наследником от TSplitter. А следовательно он не наследует проблемы TSplitter’а. TdnSplitter создан как отдельный компонент.
Вот список отличительных свойств компонента.
- TdnSplitter наследован от TCustomControl (который в свою очередь наследован от TWinControl), в отличии от TSplitter, который наследован TGraphicControl.
- Свойство AlignControl. Это свойство задаётся явно (или определяется автоматически в Design-Time). Благодаря этому случайная потеря связанного со сплиттером компонента невозможна в принципе.
- Свойство IsSnapped. Узнать, скрыт ли связанный компонент можно через Boolean-свойство. Через это же свойство можно скрывать/отображать связанный компонент.
- Свойство ControlSize. Это свойство позволяет узнать (или изменить) ширину связанного компонента (или высоту – в зависимости от расположения).
- Имеется кнопка для скрывания/отображения связанного компонента. Для этой кнопки можно указать Hint и ещё несколько параметров, отвечающих за внешний вид.
- Свойство AllowDrag позволяет запретить изменять размер связанного компонента перетаскиванием (т.е. можно оставить только кнопку и сплиттер будет иметь всего два положения – см. свойство IsSnapped).
- Свойство Action. TdnSplitter можно связать с Action. Если Вы пользуетесь Аction’ами, то Вы поймёте, зачем это нужно.
Благодаря свойствам IsSnapped и ControlSize сохранять и восстанавливать состояние сплиттера и связанного с ним компонента стало проще простого.
Ссылка для скачивания: Исходник компонента + исходник демо приложения + скомпилированное демо (zip-архив 209 К).
Скриншот из реального приложения:
На картинке два сплиттера: первый “раскрыт” (видна панель “Папки” и показан хинт под курсором мыши), второй “скрыт” (панель связей в правой части окна).
Компонент написан в среде Delphi 7 и без проблем должен заработать и в более поздних версиях Delphi.
P.S.: В качестве развития компонента у меня была такая идея: при скрытии связанного компонента явно менять его видимость (Visible), вместо изменения его размера в 0 (как сейчас). Однако на практике это особо мне не понадобилось и пока оно осталось как есть.
P.P.S.: В Design-Time, когда вы кидаете Splitter на форму и меняете у него привязку, у сплиттера может неправильно установиться внешний размер. Не пугайтесь :). Достаточно установить/проверить свойства Align, AlignControl и Size. Так как это проявляется редко и только в Design-Time в момент настройки компонента, я не стал себя утруждать (каюсь!) исправлением этой мелкой … “ошибки” :).
P.P.S.: Несмотря на мелкую проблему с компонентом в Design-Time, я очень надеюсь что этот пост поучаствует в конкурсе delphifeeds.ru.
33 коммент.:
Скриншот бы еще, или демку скомпилированную
Один завалящий скриншотик - не помешал бы.
А так - на первый взгляд - очень понравилось. Может заюзаю :) Надеюсь он бесплатный?
Скриншот приложил (для красоты я его взял из реального приложения а не из демки, состряпанной на скорую руку).
Скомпилированная демка есть в архиве с исходниками.
Компонент бесплатный, Вы можете использовать его на свой страх и риск без каких-либо ограничений и обязательств перед автором (т.е. передо мной) :).
Спасибо :)
Да, демку я видел. Просто пришлось весь архив качать, только что бы посмотреть о чем речь в статье. А сейчас, со скиншотом, вообще отлично.
Напоминает мне он внешний, такой же из Raize =)))
Ничего общего мой компонент с Raize не имеет:
TRzSplitter: This custom container consists of two panes separated by a splitter bar. The panes, and their contents are automatically resized when the splitter bar is moved.
А вот прорисовка кнопки... насколько мне известно, такая прорисовка (стрелки + точки с тенью) впервые появилась в Netscape навигаторе.
Спасибо)))
Очень полезная вещь!
Долго такую искал.
Отличнейший интуитивно понятный и простой компонент! Как раз нашел у вас то что было нужно и разобрался за 1 мин. даже не открывая демо!
Благодарю!
Спасибо, что не ленитесь писать комментарии!
Пользуйтесь на здоровье!
Николай!
Большое спасибо за компонент. Тоже давно не устраивает стандартный.
Единственное, что потребовалось поправить, это поведение кнопки. Интуитивно пробовал тянуть за середину, чтобы изменить размер, а срабатывала кнопка. Перенес снаппинг в MouseUp, сделал проверку на +-2 точки и получил то, что "ждал многие годы".
Спасибо.
Кстати, да! Почему бы за саму кнопку путём перетягивания не изменять размер? Хорошая мысль!
ivk, не могли бы Вы мне прислать изменения в исходнике, я бы его выложил заново? Контакты в профиле.
Отправил на gmail
Кому интересно - обновил исходник
Никогда не добавлял сторонние компоненты. Где можно глянуть алгоритм действий? У меня embarcadero RAD 2010
Delphi package я проинсталил. А компонента не добавилась. Что еще надо сделать?
В файле dnSplitter.pas есть процедура Register, которая выглядит так:
procedure Register;
begin
RegisterComponents('Delphi Notes.RU', [TdnSplitter]);
end;
Это означает, что при установке компонента TdnSplitter, он появится на вкладке 'Delphi Notes.RU' в панели компонент (сама вкладка добавится, наверное, в конец списка вкладок).
А в Delphi 2010 есть ещё возможность поиска компонент - там специальное поле ввода - попробуйте туда ввести TdnSplitter
mli2805, не забудьте также добавить каталог с исходником в меню Tools \ Options -> Environment Options \ Delphi Options \ Library - Win32 в список Library Path
Не работает в ХЕ2 криво встает.... не компилит dnSplitter.pas
Кто решал проблему? может скинуть норм компонент
Анонимный, у меня сейчас к сожалению нет XE2. Почитайте комментарий, может поможет:
http://www.delphinotes.ru/2012/05/delphi-notes-splitter.html?showComment=1336816317935#c2699450887164990205
А вообще, исходник открытый, если вам удастся исправить в нём ошибки совместимости с XE2 (3?), не поленитесь, пришлите, пожалуйста, его мне.
Контакты в профиле.
После раскрытия нажатие Ctrl приводит к Stack Overflow
> Анонимный
Да-да-да... и не только Ctrl... и не только после раскрытия, а по разным причинам это может произойти.
Я это пофиксил, но ещё не выложил исходник, выложу в ближайшее время - отпишусь отдельной заметкой
А в С++ Builder можно установить? Спасибо.
> А в С++ Builder можно установить?
Попробуйте... Я всего однажды устанавливал себе С++ Builder (чисто поглядеть), насколько помню, он прекрасно понимает pas-файлы, правда, возможно, чтобы установить компонент, придётся немного пошаманить. Поисковик вам в помощь.
Компонент нравится.
Ctrl - просто отключил onKeyDown. Но есть ещё пара нюансов. На форме 2 панели с горизонтальным сплиттером. На верхней 3 мемо с двумя вертикальными. Чтобы вертикальные сплиттеры не слиплись при запуске, приходится задавать в onCreate MemoX.Align и dnSplitterX.AlignControl, по списку.
Если у горизонтального сплиттера якорь зацеплен за низ, то при уменьшении высоты формы, если он доходит до верхней границе, то прилипает к ней, правда потом, после пары щелчков возвращается.
> Ctrl - просто отключил onKeyDown
Ошибка исправлена, архив по ссылке обновлён как раз вчера.
> Но есть ещё пара нюансов
Предлагаю из комментариев перейти к прямому общению - email/ICQ в профиле. Может вышлете текст dfm-формы?
Николай, а вы не обновляли компонент? На XE4 не работает, ругается на FAction, на несовпадение типов Edges (TBevelEdges).
Анонимный
Не обновлял и в ближайшее время не планирую. Если вдруг случится чудо - напишу отдельной заметкой.
Жаль.
Спасибо автору за компонент!
Hint кнопки у меня не работает. Заполнил в design time св-во Hint. Искал ShowHint - не нашёл.
Delphi версии 7.0
Ошибку с FAction исправил - http://www.delphinotes.ru/2015/09/delphi-notes-splitter-v109.html
Компонент без проблем работает в XE7
Установил на 10.1 Berlin Starter. Встал без проблем.
Спасибо, Николай.
Демка сплиттера по ссылке в статье не грузится с дроп-бокса (
Добавил в C++Builder Tokyo 10.2, требуются минимальные правки:
к именам модулей в Uses добавить префиксы "Winapi.", "System.", "Vcl.".
Не забываем про зависимости, иначе ругается на отсутствие OBJ.
Отличный компонент!
Отправить комментарий