Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > Visual C++/MFC/WTL > Разрабатываем крутой интерфейс |
Автор: Coocky 5.6.2006, 17:59 |
Всем начинающим -привет! В завершении своей форумской карьеры решил я вас, друзья мои, порадывать методиками разработки красивого( т.е. своего и нестандартного) интерфейса. Мы научимся с вами создавать свои кнопки с подсветкой и анимацией, прозрачностью, свои окна, с различными заливками и фоном на бекграунд, своим заголовком. Перерисуем правильно CListCtrl, CTabCtrl, Сделаем свой CProgressCtrl,Scroll,CSliderCtrl, поборемся с мерцанием и т.д. А главное поймем как все это правильно делается. Раз и навсегда. Большая просьба, сюда вопросы не задавать, а писать в ПМ. Если где будет ошибка (все мы люди ![]() Модераторов прошу закрепить эту темку, если не трудно ![]() Сейчас пора домой. а вот завтра мы с вами начнем с теории перерисовок и сделаем свои кнопки -чек ,радио и простые ![]() И так до завтра ![]() |
Автор: Coocky 6.6.2006, 10:44 | ||||||
Итак продолжаем... ![]() Для того, что б создать красивый элемент управления, нужно создать свой,отличный от стандарного ,элемент управления-другими словами -перерисовать. Где же производится перерисовка элементов управления? Обычно для этого служит обработчик сообщения WM_PAINT- OnPaint(); Однако не для всех элементов управления целесообразно это . Дальше вы увидите-что ,где когда и как делается, в каких обработчиках или функциях. Итак теперь о главнов-как правильно рисовать или другими словами : Оптимизация графики Первое, с чем сталкивается начинающий программер при попытки рисования или отрисовки элементов управления-это мигание/мерцание/блики. Это связано с тем, что наш человеческий глаз иногда замечает процесс перерисовки,когда он совпадает с определеной частотой обновления (ну вообщем я не медик и не физик, кому интересно частота-идем дружно в Google). Для того, что б избежать видимости отрисовки мы должны весь процесс скрыть. Все это уже изобретено до вас и ничего здесь нового нет. Мы будем использовать двойную буфферизацию (надеюсь правильно написал ![]() Что же это такое? Слово может и страшное (для некоторых может даже и пошлое ![]() ![]() Итак-рисуем с использованием двойной буфферизации ![]() Создадим функцию SuperDraw(); Это будет функция вашего класса. Далее код с комментариями
Вот и все. Надеюсь все понятно. ![]() Теперь о том, как же использывать эту функцию. Там, где мы будем обрабатывать сообщение WM_PAINT, в обработчик вставляем эту функцию.
Теперь избавимся от перерисовки фона нашего окна (он тоже блики дает ![]() Отловим сообщение WM_ERASEBKGND и изменим возращаемое значение обрабочика
Мы вернули TRUE, тем самым дали понять, что мы не хотим, что б система заливала наш фон своим цветом. Иначе вся графика коту под хвост. Это сообщение приходит раньше , чем WM_PAINT, и заливает наше окно свои фоном, если ему не запретить. Оно нам надо? ![]() Теперь еще одно. Для принудительной перерисовки элемента не надо вызывать Invalidate(); Нужно вызывать SuperDraw(); Почему? А это вы увидите (ощущите и заметите, когда мы с вами будем делать свой скрол ![]() OnPaint() мы избавили себя от отрисовке окна тогда , когда этого нужно системе (ну например при перекрытии окна или его SHOW/HIDE). А почему мы не рисуем с помощью CPaintDC dc(this); спросят некоторые,? Отвечу-поищите топик про использование контекстов устройств. Я уже как-то писал, поэтому повторятся не буду. Скажу лишь то, что CPaintDC доставляем частенько проблемы. Но я про это писал. Ищите ![]() Да , кстати, иногда, ели много однотипных элементов со сложной прорисовкой. то это дело можно немного ускорить, поместив SuperDraw(); не в OnPaint(), а в OnEraseBkgnd(CDC* pDC), это даст нам немного более ранню прорисовку, по сравнению с другими окнами. Хотя злоупотреблять не советую. Ибо OnEraseBkgnd(CDC* pDC) нам иногда будет нужен при определеных "махинациях" в дальнейшем. Ну вот. Почва подготовлена , теперь будем рисовать. Начнем (дальше), с кнопок ![]() |
Автор: Coocky 14.6.2006, 14:16 | ||||||||||||||||||||
Заждались? ![]() Ну как говорит Ф. Бондарчук в рекламе -"И н-н-н-начали!" ![]() Кнопки. Часть 1. Нажми на кнопку-получишь результат, И твоя мечта осуществится.. Сегодня мы создадим ХР кнопки радио и чек. Без всякого манифеста. ![]() Итак. Создаем диалог. Сразу говорю, на будущее, в его свойствах выставим WS_CLIPCHILDREN , которое скажет ему. что при своей перерисовке, он не будет перерисовывать дочерние элементы. На одно мигание меньше ![]() Создадим две кнопки-butt1 и butt2 (пардон за неоригинальность ![]() Создадим два класса 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 ![]() ![]() Пример прилагается.... Далее мы продолжим изучение кнопок-в частности научимся делать плавную подсветку. |
Автор: Coocky 14.6.2006, 14:40 |
P.S. На самом деле можно (и нужно-не берите дурной пример ![]() ![]() 1.GetBitmap()-если вы не работаете со списком изображений, а конректно с битмапами. Ну и соотвествено в своих созданых функциях ( SetPress(), SetHover(), SetCheck и т.д.) делать всю логику ну и SetBitmap() соответсвенно ![]() 2. Для списков изображений держать переменную, которая ,исходя из вышесказаного в пункте 1, будет менять свое значение на нужное для всего одного вызова CImageList::Draw( // тут номер нужной картинки) в перерисовке. |
Автор: takedo 6.7.2006, 07:23 | ||
Coocky,
Хочу заметить, что мы тем самым не только избавляемся от лишней перерисовки, но и от просто крайне неприятного закрашивания контролов - см. пост: http://forum.vingrad.ru/index.php?showtopic=102364 - и картинку к нему. |
Автор: a11en 19.3.2007, 13:37 |
Простите за глупый вопрос но как запустить пример, какой файл надо открыть или запустить? |
Автор: vinter 19.3.2007, 23:53 |
с расширением .project или .dsw |
Автор: Earnest 14.5.2007, 18:41 |
Там есть *.sln. Вот его и загружай в среду. |
Автор: Samotnik 16.5.2007, 01:54 |
2 Earnest У меня Visual 6 и .sln у мя не открывается Я делаю следущее 1 Запускаю студию пустую 2 Перетаскиваю .dsw в проект ну и тд работаю дальше Вод. Я открыл студию, перетащил у мя открылась среда а в ней 10-15 строчек кода кот даже откомпилить нельзя!!! Т.к. не посвечивается компиляция. Посоветуйте что нить мож я не правильно загружаю ???? |
Автор: Earnest 16.5.2007, 11:07 |
Просто 6я среда не знает формата 7й, что понятно. Сделай новый проект и добавь туда все исходники руками. |
Автор: Fighter 13.7.2007, 07:05 |
В принципе понятна логика рисования на заднем плане. Я даже своё писал, вроде все работает. Но, вопрос такой. А что если мне нужно рисовать на устройстве, у которого режим координат например MM_HIMETRIC. Как я ни пробовал устанавливать его, не работает. Он даже содержимое окна отказывается отрисовывать. |
Автор: NPU_gh0st 7.12.2007, 11:44 |
а когда продолжение будет? CListCtrl и т.д. или я что-то пропустил??? |
Автор: black_priest 7.12.2007, 12:48 |
Да-да, между прочим, хотелось бы ![]() |
Автор: mzconcept 2.6.2008, 12:26 |
Модератор: Сообщение скрыто. |
Автор: vova4 28.7.2014, 00:12 |
подскажите пожалуйста я только начал изучать qt c++ я написал с книшки програму #include<QtGui> int main(int dd,char**ff) { QApplication tt(dd,ff); QPixmap aa; aa.load("mira.jpg"); QLabel dl; dl.resize(aa.size()); dl.setPixmap(aa); dl.show(); return tt.exec(); Добавлено через 8 минут и 45 секунд подскажите пожалуйста я только начал изучать qt c++ я написал с книшки програму #include<QtGui> int main(int dd,char**ff) { QApplication tt(dd,ff); QPixmap aa; aa.load("mira.jpg"); QLabel dl; dl.resize(aa.size()); dl.setPixmap(aa); dl.show(); return tt.exec(); } что означает строка// aa.load("maria.jpg") ? и "maria.jpg" если ето файл то где он находится и как его создать.? |
Автор: LeonidPr 28.7.2014, 07:10 | ||
Должен находиться в папке с .exe программы, а создать можно фотиком или в паинте |
Автор: vova4 28.7.2014, 19:17 |
я вставил файл .jpg в папку debug где находится .ехе , програма нормально компилируется и появляется рамка как и раньше пустая без фото что делать? |
Автор: HANDLE 17.4.2015, 14:58 |
Мартышкин труд. Пользователя вашей программы нужен этот ваш нестандартный и якобы красивый интерфейс? Лично я все приложения с подобными извратами выкидываю навсегда. |