День добрый!
Столкнулся сейчас с задачей вывода кнопки с картинкой. В принципе, все понятно, только есть одно НО (точнее, два):
1. Картинка представляет собой BMP файл, за цвет фона принимается RGB(255, 0, 255). Поскольку в нормальном случае
DrawState выводит ее "как есть", используем TransparentBlt с нашим цветом прозрачности.
2. При выводе той же картинки через DrawState с флагом DSS_DISABLED, получаем на выходе серый прямоугольник, что не есть красиво.
Собственно, вопрос: можно-ли как-нибудь указать DrawState прозрачный цвет, или на основании имеющейся картинки
создать приемлемую для DrawState (или иной функции вывода) ?
Здравствуйте, Vaynamond, Вы писали:
V>1. Картинка представляет собой BMP файл, за цвет фона принимается RGB(255, 0, 255). Поскольку в нормальном случае V>DrawState выводит ее "как есть", используем TransparentBlt с нашим цветом прозрачности.
Нужно такую дырку, чтобы были видны контролы под кнопкой? Или просто заменить прозрачный цвет на фон окна текущей темы?
Здравствуйте, Alexander G, Вы писали:
AG>Здравствуйте, Vaynamond, Вы писали:
V>>1. Картинка представляет собой BMP файл, за цвет фона принимается RGB(255, 0, 255). Поскольку в нормальном случае V>>DrawState выводит ее "как есть", используем TransparentBlt с нашим цветом прозрачности.
AG>Нужно такую дырку, чтобы были видны контролы под кнопкой? Или просто заменить прозрачный цвет на фон окна текущей темы?
AG>В первом случае только регионы, боюсь.
Нет, я просто хочу вывести картинку на кнопке (совместно с текстом). Под кнопкой никаких контролов нет — только диалог.
Но, поскольку картинка обычная BMP, DrawState выводит ее всю. Я не нашел способа дать понять DrawState, что в данном случае
прозрачным считается цвет RGB(255, 0, 255), поэтому вывожу картинку через TransparentBlt (последний параметр — цвет, который
нужно считать прозрачным).
Т.е. мне нужно или как-то дать понять DrawState, что на картинке пиксели с цветом RGB(255, 0, 255) считать прозрачными,
или найти способ самостоятельно формировать картинку "Emboss".
Здравствуйте, Vaynamond, Вы писали:
V>Нет, я просто хочу вывести картинку на кнопке (совместно с текстом). Под кнопкой никаких контролов нет — только диалог. V>Но, поскольку картинка обычная BMP, DrawState выводит ее всю.
А, то есть надо дать кнопке нарисоваться штатно, затем нарисовать свой битмап сверху?
Убрать BS_OWNERDRAW,
обрабатывать NM_CUSTOMDRAW: при CDDS_PREPAINT возвращать CDRF_NOTIFYPOSTPAINT, при CDDS_POSTPAINT — рисовать свой битмап.
(да, NM_CUSTOMDRAW для кнопки требует Common Controls 6.0, которые через манифест включаются.
А если они не используются, то таки остаться на BS_OWNERDRAW, и перед своим битмапом рисовать кнопку через DrawFrameControl, этого должно быть достаточно, ибо без Common Controls 6.0 визуальных стилей нет)
Здравствуйте, Alexander G, Вы писали:
AG>А, то есть надо дать кнопке нарисоваться штатно, затем нарисовать свой битмап сверху?
AG>Убрать BS_OWNERDRAW, AG>обрабатывать NM_CUSTOMDRAW: при CDDS_PREPAINT возвращать CDRF_NOTIFYPOSTPAINT, при CDDS_POSTPAINT — рисовать свой битмап.
Здравствуйте, Carc, Вы писали:
AG>>Убрать BS_OWNERDRAW, AG>>обрабатывать NM_CUSTOMDRAW: при CDDS_PREPAINT возвращать CDRF_NOTIFYPOSTPAINT, при CDDS_POSTPAINT — рисовать свой битмап.
C>А разве Custom Draw для кнопок поддерживается?
Здравствуйте, Carc, Вы писали:
C>А-а-а-а, виста унд выше… Тогда понятно, откуда у меня ощущение что "не-а, не поддерживается". По старинке многое писалось и тестилось на ХП…
Та не. Они просто из всей документации по мере правок удаляют старые версии Windows.
Опа, BN_CLICKED тоже типа только во времена Висты изобрели
У меня оффлайновый MSDN April 2007, в котором этого рефакторинга нет (включая упоминания Win98), и там для этого сообщения указана Windows XP. (Но да, нужен Common Controls 6.0)
AG>Та не. Они просто из всей документации по мере правок удаляют старые версии Windows. AG>Опа, BN_CLICKED тоже типа только во времена Висты изобрели
AG>У меня оффлайновый MSDN April 2007, в котором этого рефакторинга нет (включая упоминания Win98), и там для этого сообщения указана Windows XP. (Но да, нужен Common Controls 6.0)
Он-на ка-а-ак (ц)… А если Visual Styles вообще отключены пользователям, тогда как быть? Я несколько раз просил отскриншотится о проблемах своих пользователей. И хотя я точно знаю что у них Виста\7+, то частенько вижу как раз пейзаж отключенных стилей. Гуй в стиле Win2K… Ну есть фанаты\или требования какие — вот отключают стили в винде напрочь.
И как тогда быть?!?! В общем, в своих случаях я делал иначе: Субкласс\ИлиСуперКласс кнопки + перехват WM_PAINT + отрисовка по умолчанию, а уж затем свои раскраски добавлять.
Здравствуйте, Carc, Вы писали:
C>Он-на ка-а-ак (ц)… А если Visual Styles вообще отключены пользователям, тогда как быть? Я несколько раз просил отскриншотится о проблемах своих пользователей. И хотя я точно знаю что у них Виста\7+, то частенько вижу как раз пейзаж отключенных стилей. Гуй в стиле Win2K… Ну есть фанаты\или требования какие — вот отключают стили в винде напрочь.
Сам выбираю классическую тему, просто так больше нравится (меньше визуального шума).
Но фичи коммон контролов и визуальные стили ортогональны.
Ну то есть все полезности Common Control 6.0 будут на месте, хоть классическую тему выбери, хоть вообще службу тем отключи.
(Примеры других таких полезностей, что навскидку вспомню:
— Balloon Tooltip у Edit Control, для которого есть сообщение, и который сам есть при ES_NUMBER;
— готовые стрелочки в колонках в LVS_REPORT List-View )
Здравствуйте, Alexander G, Вы писали:
AG>Здравствуйте, Vaynamond, Вы писали:
V>>Нет, я просто хочу вывести картинку на кнопке (совместно с текстом).
AG>Кстати, а может просто BM_SETIMAGE ?
А вот это мысль...
Судя по табличке, в зависимости от комбинации BS_BITMAP/BM_SETIMAGE можно выводить картинку + текст в разных комбинациях.
P.S.: Сейчас попробовал, облом: выводит картинку вместе с фоном (как и DrawState)
Здравствуйте, Alexander G, Вы писали:
AG>А, то есть надо дать кнопке нарисоваться штатно, затем нарисовать свой битмап сверху?
Ну да.
AG>Убрать BS_OWNERDRAW, AG>обрабатывать NM_CUSTOMDRAW: при CDDS_PREPAINT возвращать CDRF_NOTIFYPOSTPAINT, при CDDS_POSTPAINT — рисовать свой битмап.
Тут такой вопрос возник: при отображении нормальной кнопки все просто. А когда кнопка задизейблена ?
У меня сейчас проблема именно с выводом задизейбленой кнопки.
AG>(да, NM_CUSTOMDRAW для кнопки требует Common Controls 6.0, которые через манифест включаются. AG>А если они не используются, то таки остаться на BS_OWNERDRAW, и перед своим битмапом рисовать кнопку через DrawFrameControl, этого должно быть достаточно, ибо без Common Controls 6.0 визуальных стилей нет)
Рисовать кнопку именно через DrawFrameControl ? Я сейчас использую DrawEdge — вроде кнопка получается адекватная.
Здравствуйте, Carc, Вы писали:
AG>>У меня оффлайновый MSDN April 2007, в котором этого рефакторинга нет (включая упоминания Win98), и там для этого сообщения указана Windows XP. (Но да, нужен Common Controls 6.0) C>Он-на ка-а-ак (ц)… А если Visual Styles вообще отключены пользователям, тогда как быть? Я несколько раз просил отскриншотится о проблемах своих пользователей. И хотя я точно знаю что у них Виста\7+, то частенько вижу как раз пейзаж отключенных стилей. Гуй в стиле Win2K… Ну есть фанаты\или требования какие — вот отключают стили в винде напрочь.
У меня ровно наоборот, никогда в скринах классику не видел Интересный момент.
C>И как тогда быть?!?! В общем, в своих случаях я делал иначе: Субкласс\ИлиСуперКласс кнопки + перехват WM_PAINT + отрисовка по умолчанию, а уж затем свои раскраски добавлять.
По-хорошему, надо делать разбор ситуации. Я у себя проверял версию винды, плюс включены-выключены стили, и в зависимости от этого рисовал что-то своё в каждом случае.
Конкретно сабкласс кнопки на 7+dwm приведёт к тому, что при наведении мышки винда будет пытаться рисовать свою анимацию, а сабкласс будет ловить события WM_PAINT после анимации и рисовать своё — в случае или своего бака или бака у иконки будет мельтешение в кнопке.
По теме: я бы открыл картинку в редакторе и сделал 32-битную с альфой, потом BM_SETIMAGE (я так всегда делаю)
Здравствуйте, Vaynamond, Вы писали:
V>Тут такой вопрос возник: при отображении нормальной кнопки все просто. А когда кнопка задизейблена ? V>У меня сейчас проблема именно с выводом задизейбленой кнопки.
В случае NM_CUSTOMDRAW на стадии CDDS_POSTPAINT всё уже нарисовано за нас, включая и дизейбл:
V>Рисовать кнопку именно через DrawFrameControl ? Я сейчас использую DrawEdge — вроде кнопка получается адекватная.
Через DrawFrameControl можно адекватно рисовать разные контролы (типа галочек и стрелочек) в разных состояниях.
В частности, для кнопки не надо явно задавать направление и ширину выступа.
bool button_is_pushed = true;
bool button_is_disabled = true;
UINT state = DFCS_BUTTONPUSH;
if ( button_is_pushed )
state |= DFCS_PUSHED;
if ( button_is_disabled )
state |= DFCS_INACTIVE;
CRect rect(CPoint(10, 10), CSize(72, 26));
dc.DrawFrameControl(rect, DFC_BUTTON, state);
Но это если без визуальных стилей. Со всякими DrawTheme* функциями мороки больше.
Здравствуйте, Alexander G, Вы писали:
V>>Рисовать кнопку именно через DrawFrameControl ? Я сейчас использую DrawEdge — вроде кнопка получается адекватная.
AG>Через DrawFrameControl можно адекватно рисовать разные контролы (типа галочек и стрелочек) в разных состояниях. AG>В частности, для кнопки не надо явно задавать направление и ширину выступа.
Я за основу брал пример из CodeGuru, так там еще более замороченный алгоритм: если кнопка нажата, она рисуется
с помощью FrameRect, а в остальных случаях — через DrawFrameControl.
Здравствуйте, Vaynamond, Вы писали:
AG>>Через DrawFrameControl можно адекватно рисовать разные контролы (типа галочек и стрелочек) в разных состояниях. AG>>В частности, для кнопки не надо явно задавать направление и ширину выступа.
V>Я за основу брал пример из CodeGuru, так там еще более замороченный алгоритм: если кнопка нажата, она рисуется V>с помощью FrameRect, а в остальных случаях — через DrawFrameControl.
А там у примера дата какая стоит?
CodeGuru хороший портал, удобный, с примерами, вот только жаль, что не популярный
я оттуда в своё время тоже код таскал
Здравствуйте, Alexander G, Вы писали:
AG>В случае NM_CUSTOMDRAW на стадии CDDS_POSTPAINT всё уже нарисовано за нас, включая и дизейбл:
Сейчас стал смотреть, как пару лет назад панель инструментов делал на основе ReBar'а, так там картинки передаются
через ImageList. Собственно, вопрос: с кнопками такой вариант не прокатит ?
Смущает то, что есть для добавления BMP-файла макросы Add/AddMasked, для добавления ICO-файла макрос AddIcon,
а для получения — только GetIcon. Или прямо выводить с помощью ImageList_Draw ?
Здравствуйте, CEMb, Вы писали:
CEM>Здравствуйте, Vaynamond, Вы писали:
AG>>>Через DrawFrameControl можно адекватно рисовать разные контролы (типа галочек и стрелочек) в разных состояниях. AG>>>В частности, для кнопки не надо явно задавать направление и ширину выступа.
V>>Я за основу брал пример из CodeGuru, так там еще более замороченный алгоритм: если кнопка нажата, она рисуется V>>с помощью FrameRect, а в остальных случаях — через DrawFrameControl.
CEM>А там у примера дата какая стоит? CEM>CodeGuru хороший портал, удобный, с примерами, вот только жаль, что не популярный CEM>я оттуда в своё время тоже код таскал
Здравствуйте, CEMb, Вы писали:
CEM>По теме: я бы открыл картинку в редакторе и сделал 32-битную с альфой, потом BM_SETIMAGE (я так всегда делаю)
Это не наш метод
Если серьезно, уже сложилось исторически, что все картинки у нас (в нашем проекте) обычный 24-битный BMP.
В принципе, сейчас первый раз столкнулся с проблемой вывода картинки — все остальное выводится без проблем.
P.S.: Короче, выкрутился через ImageList. Добавляю туда BMP-шку с маской RGB(255, 0, 255), а в WM_DRAWITEM дергаю
ImageList_GetIcon(..., ILD_TRANSPARENT) и скармливаю полученный хендл функции DrawState. В итоге корректно выводится
и штатная картинка, и задизейбленая.