Партнерка на США и Канаду по недвижимости, выплаты в крипто
- 30% recurring commission
- Выплаты в USDT
- Вывод каждую неделю
- Комиссия до 5 лет за каждого referral
ScrollableControl с дополнительным возможностями
Олег Михайлик, май 2004
Архитектура Windows Forms удобна для расширения и написания самодельных гениальных контролов. Любой начинающий программист за 20 минут напишет свой MySuperLabel с эффектом тени от текста. Или даже анимации! Да каждый второй имел на своём счету подобный грешок :-)
Нет каких-то особых препятствий и для написания действительно сложных и серьёзных контролов. От календарей до таблиц и просмотра увеличенных изображений.
Препятствий-то нет, но есть некоторые места, где можно было бы сделать WinForms чуть лучше. В одном или втором контроле не хватает такого или другого штриха, свойства, детали. Многие из подобных шероховатостей будут исправлены уже в следующем релизе. NET Framework, до выхода бета-версии которого осталось уже совсем немного дней. Многие, но не все. Я расскажу об одной такой возможности, которую я реализовал в своём переработанном ScrollableControl.
Просмотр больших картинок
Представим себе контрол, предназначенный для Image Preview. Необходимо увеличивать изображение, уменьшать, прокручивать для просмотра разных частей картинки в увеличенном масштабе.
Фактически, здесь нужно перегрузить метод OnPaint и рисовать какую-то часть картинки с учётом увеличения и прокрутки.
Вопрос в том, что нужен контрол, предоставляющий возможность такой прокрутки. Мы хотим сказать контролу: у тебя внутри объект размером PixelWidth x PixelHeight, обеспечь соответствующие полосы и прокрутку.
В существующей архитектуре нужно или использовать 2 контрола ScrollBar, расположив их по бокам, или класть внутри нашего контрола некий огромный Panel. В обоих случаях мы получим некоторые неприятные мелкие проблемы, которых хотелось бы избежать.
Дело в том, что явные контролы ScrollBar на системном уровне Windows будут считаться отдельными дочерними окнами нашего Image Viewer’а. Это может привести к артефактам с передачей фокуса, сообщений клавиатуры, колёсиком мыши и т. д. Те же минусы и у подложного внутреннего Panel. Всё-таки желательно, чтобы наш Image Viewer был простым родным однооконным контролом для Windows.
Это можно сделать. Нужно только разобраться с низкоуровневыми функциями прокрутки Win32 API, со стилями окна и прочей никому не нужной ерундой.
Исходники, естественно, прилагаются.
Как это использовать
Для нас существуют всего две объективные вещи. Звездное небо над нами и нравственный закон внутри нас.
Эти два свойства определяют и работу ScrollableControl: ContentSize и ContentShift. Первое определяет тот «виртуальный» размер внутреннего контента, который будет прокручиваться в окне.
А уж ContentShift показывает, насколько смещён «виртуальный контент» в результате прокрутки. Смещение отражено как положительные значения координат.
Оба свойства доступны как на чтение, так и на запись. При записи автоматически обновляется контрол.
Точки приложения
Где нужна такая функциональность? Так ведь вот где!
Просмотр (а также редактирование) изображений
Пример, собственно, прилагается. В данном случае простейший «вьювер» позволяет увеличивать-уменьшать изображение, и прокручивать как через полосы прокрутки, так и «перетаскивая» его в окошке.
Картография
Ваш заказчик хочет видеть карту своих объектов на экране? ОК, почему нет. Всё, что вам нужно — обеспечить отрисовку, благо. NET Framework имеет для этого мощную подсистему GDI+.
Начните с того же примера ImageViewer. Переопределите отрисовку для отображения карты, с учётом Zoom. Так у вас будет сразу готовый контрол с возможностью прокрутки, увеличения, уменьшения карты.
Графики, диаграммы
В сущности, примерно та же специфика, что для картографии. Причём в обоих случаях стоит поразмыслить над буферизацией сложной графики.
Гриды и таблицы
Это как раз именно то, ради чего мне был нужен ScrollableControl. Вместе с исходниками вы можете посмотреть текущий проект моего грида.
Здесь же, в классе TreeBase реализована достаточно функциональная буферизация. Например, при прокрутке перерисовывается только вновь появившаяся часть контента, а не весь “window client rectangle”.


