|
|
|
Coocky |
|
|||
GUI гуру Профиль Группа: Участник Клуба Сообщений: 2879 Регистрация: 16.2.2004 Где: Украина. Запорожь е Репутация: 25 Всего: 62 |
Всем начинающим -привет!
В завершении своей форумской карьеры решил я вас, друзья мои, порадывать методиками разработки красивого( т.е. своего и нестандартного) интерфейса. Мы научимся с вами создавать свои кнопки с подсветкой и анимацией, прозрачностью, свои окна, с различными заливками и фоном на бекграунд, своим заголовком. Перерисуем правильно CListCtrl, CTabCtrl, Сделаем свой CProgressCtrl,Scroll,CSliderCtrl, поборемся с мерцанием и т.д. А главное поймем как все это правильно делается. Раз и навсегда. Большая просьба, сюда вопросы не задавать, а писать в ПМ. Если где будет ошибка (все мы люди )-писать то же в ПМ. Модераторов прошу закрепить эту темку, если не трудно Сейчас пора домой. а вот завтра мы с вами начнем с теории перерисовок и сделаем свои кнопки -чек ,радио и простые И так до завтра Это сообщение отредактировал(а) Coocky - 5.6.2006, 18:07 -------------------- Верю в смерть после жизни, в любовь после секса ,в крем после бритья |
|||
|
||||
Coocky |
|
||||||
GUI гуру Профиль Группа: Участник Клуба Сообщений: 2879 Регистрация: 16.2.2004 Где: Украина. Запорожь е Репутация: 25 Всего: 62 |
Итак продолжаем...
Для того, что б создать красивый элемент управления, нужно создать свой,отличный от стандарного ,элемент управления-другими словами -перерисовать. Где же производится перерисовка элементов управления? Обычно для этого служит обработчик сообщения WM_PAINT- OnPaint(); Однако не для всех элементов управления целесообразно это . Дальше вы увидите-что ,где когда и как делается, в каких обработчиках или функциях. Итак теперь о главнов-как правильно рисовать или другими словами : Оптимизация графики Первое, с чем сталкивается начинающий программер при попытки рисования или отрисовки элементов управления-это мигание/мерцание/блики. Это связано с тем, что наш человеческий глаз иногда замечает процесс перерисовки,когда он совпадает с определеной частотой обновления (ну вообщем я не медик и не физик, кому интересно частота-идем дружно в Google). Для того, что б избежать видимости отрисовки мы должны весь процесс скрыть. Все это уже изобретено до вас и ничего здесь нового нет. Мы будем использовать двойную буфферизацию (надеюсь правильно написал ) Что же это такое? Слово может и страшное (для некоторых может даже и пошлое ), но на самом деле все просто "до немогу". Мы рисуем все на "заднем", невидимом плане. А после этого всю картинку передаем битовыми блоками в один прием на "видимое полотно" (передача блитов из памяти-самый быстрый метод. Насколько я знаю ). Вообщем все до банальности просто. Мигания вы не увидите. Максимум что вам светит-медленая (заторможеная прорисовка), если приходится много рисовать или передовать большие растровые изображения. Итак-рисуем с использованием двойной буфферизации Создадим функцию SuperDraw(); Это будет функция вашего класса. Далее код с комментариями
Вот и все. Надеюсь все понятно. Теперь о том, как же использывать эту функцию. Там, где мы будем обрабатывать сообщение WM_PAINT, в обработчик вставляем эту функцию.
Теперь избавимся от перерисовки фона нашего окна (он тоже блики дает ) Отловим сообщение WM_ERASEBKGND и изменим возращаемое значение обрабочика
Мы вернули TRUE, тем самым дали понять, что мы не хотим, что б система заливала наш фон своим цветом. Иначе вся графика коту под хвост. Это сообщение приходит раньше , чем WM_PAINT, и заливает наше окно свои фоном, если ему не запретить. Оно нам надо? Теперь еще одно. Для принудительной перерисовки элемента не надо вызывать Invalidate(); Нужно вызывать SuperDraw(); Почему? А это вы увидите (ощущите и заметите, когда мы с вами будем делать свой скрол ). Замечу лишь то, что поместив SuperDraw() в обработчик OnPaint() мы избавили себя от отрисовке окна тогда , когда этого нужно системе (ну например при перекрытии окна или его SHOW/HIDE). А почему мы не рисуем с помощью CPaintDC dc(this); спросят некоторые,? Отвечу-поищите топик про использование контекстов устройств. Я уже как-то писал, поэтому повторятся не буду. Скажу лишь то, что CPaintDC доставляем частенько проблемы. Но я про это писал. Ищите Да , кстати, иногда, ели много однотипных элементов со сложной прорисовкой. то это дело можно немного ускорить, поместив SuperDraw(); не в OnPaint(), а в OnEraseBkgnd(CDC* pDC), это даст нам немного более ранню прорисовку, по сравнению с другими окнами. Хотя злоупотреблять не советую. Ибо OnEraseBkgnd(CDC* pDC) нам иногда будет нужен при определеных "махинациях" в дальнейшем. Ну вот. Почва подготовлена , теперь будем рисовать. Начнем (дальше), с кнопок -------------------- Верю в смерть после жизни, в любовь после секса ,в крем после бритья |
||||||
|
|||||||
Coocky |
|
||||||||||||||||||||
GUI гуру Профиль Группа: Участник Клуба Сообщений: 2879 Регистрация: 16.2.2004 Где: Украина. Запорожь е Репутация: 25 Всего: 62 |
Заждались?
Ну как говорит Ф. Бондарчук в рекламе -"И н-н-н-начали!" Кнопки. Часть 1. Нажми на кнопку-получишь результат, И твоя мечта осуществится.. Сегодня мы создадим ХР кнопки радио и чек. Без всякого манифеста. Итак. Создаем диалог. Сразу говорю, на будущее, в его свойствах выставим WS_CLIPCHILDREN , которое скажет ему. что при своей перерисовке, он не будет перерисовывать дочерние элементы. На одно мигание меньше Создадим две кнопки-butt1 и butt2 (пардон за неоригинальность ) Поставим им свойство BS_OWNERDRAW- значит, что рисовать будем сами. Создадим два класса class CRadioButton : public CButton и class CheckButton : public CButton (далее буду рассматоривать один класс, а в примере есть все для всех ) Перегрузим виртуальную функцию void CheckButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) Эта функция вызывается вседа, когда элемент требует перерисовки. Заполняем ее
Там все с коментариями Теперь ловим сообщение WM_ERASEBKGND
И ловим WM_MOUSEMOVE Если мышь над кнопкой подсветим ее
Теперь подробнее о TRACKMOUSEEVENT Нам нужно знать о том, когда же "погасить кнопку". Гасить нужно тогда, когда мышь выходит за пределы кнопки. Для этого мы должны сделать
Это позволить нам ловить сообщение WM_MOUSELEAVE,что означает-мышь не над кнопкой Ну и соотвествено поймам сообщение.обработать его
Ну и соотвествено теперь обработаем нажатие кнопки (я это сделал,для простоты, в классе окна. Хотя можно пойти дальше и обработать нажатие и тпускание кнопки в классе кнопки) Для этого создаем две функции :
И получение флага нажатия
Ну и само нажатие
Вот и вся основа. Пример конечно очень простой. Все можно разширить функциями класса нашей кнопки. Вплоть до установления картинок, цвета текста ,размера шрифта и т.д.. В итоге можно создать свой универсальный класс кнопки. Или dll . И ненадо лазить в поисках других библиотек.Это уже вам карты в руки Да, чуть не забыл. Обратите внимание на класс CRadioButton . Там я создал список изображения с маской прозрачности. Чтоб квадратная икона "обрезалась" до круглой.
далее при рисовании
Да..И еще. Нажати кнопки и подсветка происходит не только на самой картинки, а и чуть правее (по всей ширине кнопки.) Кому не нравится, ограничте проверко попадание на прямоугольник функцией CRect::PtInRect(); Это для самостоятельной работы Ну вроде и все. За код не ругайте. Если где ошибочка-издержки copy-paste Ну нет у меня времени, нет Пример прилагается.... Далее мы продолжим изучение кнопок-в частности научимся делать плавную подсветку. Присоединённый файл ( Кол-во скачиваний: 803 ) button.rar 54,83 Kb -------------------- Верю в смерть после жизни, в любовь после секса ,в крем после бритья |
||||||||||||||||||||
|
|||||||||||||||||||||
Coocky |
|
|||
GUI гуру Профиль Группа: Участник Клуба Сообщений: 2879 Регистрация: 16.2.2004 Где: Украина. Запорожь е Репутация: 25 Всего: 62 |
P.S.
На самом деле можно (и нужно-не берите дурной пример ) обойтись без всех сложных конструкций if else в перерисовке (это сделано вам для наглядности процесса).Представьте сколько их будет когда мы захотим еще отрисовать и нажатие кнопки и отпускание и еще что-нибудь. Вместо этого нужно использовать: 1.GetBitmap()-если вы не работаете со списком изображений, а конректно с битмапами. Ну и соотвествено в своих созданых функциях ( SetPress(), SetHover(), SetCheck и т.д.) делать всю логику ну и SetBitmap() соответсвенно 2. Для списков изображений держать переменную, которая ,исходя из вышесказаного в пункте 1, будет менять свое значение на нужное для всего одного вызова CImageList::Draw( // тут номер нужной картинки) в перерисовке. -------------------- Верю в смерть после жизни, в любовь после секса ,в крем после бритья |
|||
|
||||
takedo |
|
|||
Опытный Профиль Группа: Участник Сообщений: 501 Регистрация: 1.6.2005 Репутация: нет Всего: 3 |
Coocky,
Хочу заметить, что мы тем самым не только избавляемся от лишней перерисовки, но и от просто крайне неприятного закрашивания контролов - см. пост: http://forum.vingrad.ru/index.php?showtopic=102364 - и картинку к нему. -------------------- я не гольфист - я хоккеист |
|||
|
||||
a11en |
|
|||
Шустрый Профиль Группа: Участник Сообщений: 64 Регистрация: 4.11.2006 Где: Ставрополь Репутация: нет Всего: нет |
Простите за глупый вопрос но как запустить пример, какой файл надо открыть или запустить?
|
|||
|
||||
vinter |
|
|||
Explorer Профиль Группа: Завсегдатай Сообщений: 2735 Регистрация: 1.4.2006 Где: Н.Новгород Репутация: 4 Всего: 56 |
с расширением .project или .dsw
|
|||
|
||||
Samotnik |
|
|||
Super star ! Профиль Группа: Awaiting Authorisation Сообщений: 7192 Регистрация: 4.11.2006 Где: Минск City Репутация: 1 Всего: 191 |
||||
|
||||
Earnest |
|
|||
Эксперт Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
Там есть *.sln. Вот его и загружай в среду.
-------------------- ... |
|||
|
||||
Samotnik |
|
|||
Super star ! Профиль Группа: Awaiting Authorisation Сообщений: 7192 Регистрация: 4.11.2006 Где: Минск City Репутация: 1 Всего: 191 |
2 Earnest
У меня Visual 6 и .sln у мя не открывается Я делаю следущее 1 Запускаю студию пустую 2 Перетаскиваю .dsw в проект ну и тд работаю дальше Вод. Я открыл студию, перетащил у мя открылась среда а в ней 10-15 строчек кода кот даже откомпилить нельзя!!! Т.к. не посвечивается компиляция. Посоветуйте что нить мож я не правильно загружаю ???? |
|||
|
||||
Earnest |
|
|||
Эксперт Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
Просто 6я среда не знает формата 7й, что понятно.
Сделай новый проект и добавь туда все исходники руками. -------------------- ... |
|||
|
||||
Fighter |
|
|||
Опытный Профиль Группа: Участник Сообщений: 810 Регистрация: 5.1.2005 Репутация: нет Всего: 2 |
В принципе понятна логика рисования на заднем плане. Я даже своё писал, вроде все работает. Но, вопрос такой. А что если мне нужно рисовать на устройстве, у которого режим координат например MM_HIMETRIC. Как я ни пробовал устанавливать его, не работает. Он даже содержимое окна отказывается отрисовывать.
|
|||
|
||||
NPU_gh0st |
|
|||
Новичок Профиль Группа: Участник Сообщений: 8 Регистрация: 22.10.2007 Репутация: нет Всего: нет |
а когда продолжение будет? CListCtrl и т.д. или я что-то пропустил???
|
|||
|
||||
black_priest |
|
|||
Шустрый Профиль Группа: Участник Сообщений: 63 Регистрация: 19.3.2007 Где: Minsk Репутация: нет Всего: нет |
Да-да, между прочим, хотелось бы
|
|||
|
||||
mzconcept |
|
|||
Новичок Профиль Группа: Участник Сообщений: 38 Регистрация: 7.5.2008 Репутация: нет Всего: нет |
Модератор: Сообщение скрыто. |
|||
|
||||
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Visual C++/MFC/WTL | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |