Сейчас работаю над очередным проектом. Проект большой, занимает все мое рабочее и свободное время утром и вечером включая выходные и праздничные дни. Даже на статью в Дзене не могу найти времени. Вот я и решил написать по теме того над чем я сейчас работаю.
В очередной раз возникла необходимость использовать уже написанный ранее код, который нужно немного "допилить" для текущего проекта. И начинается процесс называемый в народе "Копипаст". Называется он так потому, что 99,9% действий которые осуществляет пользовать это "Копировать" и "Вставить". Ну, если по-английски, то "Copy" и "Paste" соответственно. Вот и получается "Копипаст". Этот подход конечно работает неплохо, но только вот требует постоянного переделывания логики работы скопированных элементов.
Возникает необходимость один раз создать некий "универсальный" компонент, который потом можно будет просто перетащить на форму и получить что нам необходимо. Такие компоненты, конечно же, уже есть. Это различные формы (окна), кнопки, списки, текстовые метки и еще примерно пара десятков других самых распространенных. На этих компонентах построены все программы в любой операционной системе. Даже на мобильных телефонах есть кнопки, окна, метки, списки и т.п.
Эти элементы можно не только использовать по отдельности, но и создавать на их основе другие элементы с нужным нам функционалом. Вот и сейчас передо мной встала задача сделать некий универсальный элемент управления, который будет обладать заранее заложенный функционал. Можно еще создать один элемент управления, в составе которого будут находится другие элементы управления, но при этом они будут единым целым. Об этом смотрите в следующих статьях.
В чем преимущество, спросите вы? А я отвечу. Преимущество в том, что раз за разом приходится размещать на форме одни и те же элементы в одном и том же порядке и настраивать для них одинаковый функционал с точностью до запятой. При этом еще следить за тем, чтобы на разных формах совпадало абсолютно все - от размеров до расстояний между другими элементами.
При создании нового элемента существует и недостаток - необходимо затратить время на создание компонента. При этом времени будет затрачено больше чем небольшие доработки "стандартных" элементов. Это связано с тем, что при создании компонента нам необходимо создать максимально универсальный элемент который предусматривает все мыслимые и не мыслимые варианты развития событий. Но это уже будет вершина идеала. Но даже затраченное время с лихвой окупится в дальнейшем, когда мы начнем использовать созданный нами элемент и не будем отвлекаться на создание одинакового функционала.
Например, понадобилось чтобы абсолютно на всех окнах программы был одинаковый заголовок в виде логотипа фирмы. Можно, конечно, после создания формы скопировать логотип с другой формы и вставить на новую. Но что произойдет когда логотип изменится или нужен будет такой же, но "с перламутровыми пуговицами"? Правильно, нужно будет удалить все скопированные ранее логотипы и вместо них вставить новые логотипы. Это может занять не один рабочий день. В случае использования компонента с логотипом нам необходимо сделать изменения только в коде компонента и на всех формах он изменится. Надеюсь у вас родилось понимание того как работают компоненты.
Первый элемент, который я создам для своей программы - это кнопка. От обычной кнопки она будет отличаться внешним видом и своим "поведением" при нажатии и наведении указателя мыши.
Листайте галерею, в которой показана кнопка в разных состояниях (обычное, при наведении мышки, нажатое)
Забегая вперед скажу, что мой проект в котором я использую эту кнопку готов примерно на 70%, и в нем уже больше 100 этих кнопок. Это связано с тем, что проект большой, много разных окон (планируется порядка 30) и в каждом окне по 5-10 кнопок разного назначения. Но все они должны обладать единым функционалом и выглядеть одинаково. Для этого я и использую этот созданный в самом начале работы над проектом элемент управления.
Итак, приступим
Для начала нам необходимо создать класс производный от "классической" кнопки. Можно было бы все сделать с нуля, но зачем когда более 90% функционала который предоставляет стандартная кнопка нас устраивает.
Создаем класс и пару переменных, которые будут содержать текущее состояние кнопки. Поскольку мы будем еще играть со шрифтами, то опишем переменную SF в которой будет измененный формат нашего текста.
Мы хотим использовать стандартные события кнопки, но немного изменив реакцию на эти события. Поэтому нам необходимо их переопределить (команда override). Теперь, при возникновении этих событий, программа будет выполнять наши команды.
OnMouseEnter - мышка находится над элементом управления
OnMouseLeave - мышка покинула зону элемента управления
OnMouseDown - Кнопка мышки нажата
OnMouseUp - Кнопка мышки отпущена
Есть еще событие OnMouseClick, которое вызывается при щелчке мышки. Но оно в данном случае нам не подойдет, т.к. мы хотим обрабатывать именно нажатие и отпускание кнопки мыши.
В этих командах мы "запоминаем" состояние которое нам необходимо в дальнейшем обработать при прорисовке самой кнопки.
Ну и осталось дело за малым - переопределить стандартную процедуру OnPaint, которая вызывается при прорисовке компонента.
Не забываем в начале вызвать событие OnPain базового класса. Если этого не сделать, то возможно будет непонятное поведение компонента.
При наведении мышкой на кнопку изменяется значение переменной MouseEntered, которую мы указывали в самом начале, и в соответствии с этим при перерисовке кнопка закрашивается нежно-розовым цветом. Также текст на кнопке выделяется полужирным шрифтом.
Нажатие на кнопку меняет переменную MousePressed (в событии OnMouseDown которое описано выше) и цвет заливки кнопки меняется на чуть более темный чтобы было ясно что кнопку действительно нажали.
Все остальные действия выполняются в соответствии с действиями которые предоставляет стандартная кнопка, от которой мы наследовались в самом начале.
После компиляции этого кода на панели инструментов появится наша новая кнопка, которую можно просто перетащить на нужное место. При этом, если захочется изменить что-то в поведении кнопки, то эти изменения нужно будет сделать всего лишь 1 раз в исходном коде только что созданного класса. А если бы я использовал стандартную кнопку, то мне пришлось бы проводить изменения для каждой добавленной кнопки. А это очень долго и велика вероятность ошибки.
В следующих публикациях будут новые компоненты которые могут упростить жизнь и ускорить написание программ.