Партнерка на США и Канаду по недвижимости, выплаты в крипто

  • 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”.