BS_OWNERDRAW и DrawState
От: Vaynamond Россия  
Дата: 29.06.17 09:36
Оценка:
День добрый!
Столкнулся сейчас с задачей вывода кнопки с картинкой. В принципе, все понятно, только есть одно НО (точнее, два):
1. Картинка представляет собой BMP файл, за цвет фона принимается RGB(255, 0, 255). Поскольку в нормальном случае
DrawState выводит ее "как есть", используем TransparentBlt с нашим цветом прозрачности.
2. При выводе той же картинки через DrawState с флагом DSS_DISABLED, получаем на выходе серый прямоугольник, что не есть красиво.

Собственно, вопрос: можно-ли как-нибудь указать DrawState прозрачный цвет, или на основании имеющейся картинки
создать приемлемую для DrawState (или иной функции вывода) ?
Re: BS_OWNERDRAW и DrawState
От: Alexander G Украина  
Дата: 29.06.17 10:09
Оценка:
Здравствуйте, Vaynamond, Вы писали:

V>1. Картинка представляет собой BMP файл, за цвет фона принимается RGB(255, 0, 255). Поскольку в нормальном случае

V>DrawState выводит ее "как есть", используем TransparentBlt с нашим цветом прозрачности.

Нужно такую дырку, чтобы были видны контролы под кнопкой? Или просто заменить прозрачный цвет на фон окна текущей темы?

В первом случае только регионы, боюсь.
Русский военный корабль идёт ко дну!
Re[2]: BS_OWNERDRAW и DrawState
От: Vaynamond Россия  
Дата: 29.06.17 10:58
Оценка:
Здравствуйте, 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".
Re[3]: BS_OWNERDRAW и DrawState
От: Alexander G Украина  
Дата: 29.06.17 16:34
Оценка:
Здравствуйте, 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 визуальных стилей нет)
Русский военный корабль идёт ко дну!
Отредактировано 29.06.2017 16:43 Alexander G . Предыдущая версия .
Re[4]: BS_OWNERDRAW и DrawState
От: Carc Россия https://vk.com/gosha_mazov
Дата: 29.06.17 16:43
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>А, то есть надо дать кнопке нарисоваться штатно, затем нарисовать свой битмап сверху?


AG>Убрать BS_OWNERDRAW,

AG>обрабатывать NM_CUSTOMDRAW: при CDDS_PREPAINT возвращать CDRF_NOTIFYPOSTPAINT, при CDDS_POSTPAINT — рисовать свой битмап.

А разве Custom Draw для кнопок поддерживается?
Aml Pages Home
Re[5]: BS_OWNERDRAW и DrawState
От: Alexander G Украина  
Дата: 29.06.17 16:45
Оценка: 6 (1)
Здравствуйте, Carc, Вы писали:

AG>>Убрать BS_OWNERDRAW,

AG>>обрабатывать NM_CUSTOMDRAW: при CDDS_PREPAINT возвращать CDRF_NOTIFYPOSTPAINT, при CDDS_POSTPAINT — рисовать свой битмап.

C>А разве Custom Draw для кнопок поддерживается?


Дык, ссылка выше NM_CUSTOMDRAW (button) notification code
Русский военный корабль идёт ко дну!
Re[6]: BS_OWNERDRAW и DrawState
От: Carc Россия https://vk.com/gosha_mazov
Дата: 29.06.17 17:08
Оценка: +1
C>>А разве Custom Draw для кнопок поддерживается?

AG>Дык, ссылка выше NM_CUSTOMDRAW (button) notification code

Спасибо!

А-а-а-а, виста унд выше… Тогда понятно, откуда у меня ощущение что "не-а, не поддерживается". По старинке многое писалось и тестилось на ХП…
Aml Pages Home
Re[3]: BS_OWNERDRAW и DrawState
От: Alexander G Украина  
Дата: 29.06.17 17:23
Оценка:
Здравствуйте, Vaynamond, Вы писали:

V>Нет, я просто хочу вывести картинку на кнопке (совместно с текстом).


Кстати, а может просто BM_SETIMAGE ?
Русский военный корабль идёт ко дну!
Re[7]: BS_OWNERDRAW и DrawState
От: Alexander G Украина  
Дата: 29.06.17 17:28
Оценка: 3 (1)
Здравствуйте, Carc, Вы писали:

C>А-а-а-а, виста унд выше… Тогда понятно, откуда у меня ощущение что "не-а, не поддерживается". По старинке многое писалось и тестилось на ХП…


Та не. Они просто из всей документации по мере правок удаляют старые версии Windows.
Опа, BN_CLICKED тоже типа только во времена Висты изобрели

У меня оффлайновый MSDN April 2007, в котором этого рефакторинга нет (включая упоминания Win98), и там для этого сообщения указана Windows XP. (Но да, нужен Common Controls 6.0)
Русский военный корабль идёт ко дну!
Отредактировано 29.06.2017 17:30 Alexander G . Предыдущая версия . Еще …
Отредактировано 29.06.2017 17:29 Alexander G . Предыдущая версия .
Re[8]: BS_OWNERDRAW и DrawState
От: Carc Россия https://vk.com/gosha_mazov
Дата: 29.06.17 18:58
Оценка:
AG>Та не. Они просто из всей документации по мере правок удаляют старые версии Windows.
AG>Опа, BN_CLICKED тоже типа только во времена Висты изобрели

AG>У меня оффлайновый MSDN April 2007, в котором этого рефакторинга нет (включая упоминания Win98), и там для этого сообщения указана Windows XP. (Но да, нужен Common Controls 6.0)

Он-на ка-а-ак (ц)… А если Visual Styles вообще отключены пользователям, тогда как быть? Я несколько раз просил отскриншотится о проблемах своих пользователей. И хотя я точно знаю что у них Виста\7+, то частенько вижу как раз пейзаж отключенных стилей. Гуй в стиле Win2K… Ну есть фанаты\или требования какие — вот отключают стили в винде напрочь.

И как тогда быть?!?! В общем, в своих случаях я делал иначе: Субкласс\ИлиСуперКласс кнопки + перехват WM_PAINT + отрисовка по умолчанию, а уж затем свои раскраски добавлять.
Aml Pages Home
Re[9]: BS_OWNERDRAW и DrawState
От: Alexander G Украина  
Дата: 29.06.17 19:26
Оценка:
Здравствуйте, Carc, Вы писали:

C>Он-на ка-а-ак (ц)… А если Visual Styles вообще отключены пользователям, тогда как быть? Я несколько раз просил отскриншотится о проблемах своих пользователей. И хотя я точно знаю что у них Виста\7+, то частенько вижу как раз пейзаж отключенных стилей. Гуй в стиле Win2K… Ну есть фанаты\или требования какие — вот отключают стили в винде напрочь.


Сам выбираю классическую тему, просто так больше нравится (меньше визуального шума).

Но фичи коммон контролов и визуальные стили ортогональны.

Ну то есть все полезности Common Control 6.0 будут на месте, хоть классическую тему выбери, хоть вообще службу тем отключи.

(Примеры других таких полезностей, что навскидку вспомню:
— Balloon Tooltip у Edit Control, для которого есть сообщение, и который сам есть при ES_NUMBER;
— готовые стрелочки в колонках в LVS_REPORT List-View )
Русский военный корабль идёт ко дну!
Re[4]: BS_OWNERDRAW и DrawState
От: Vaynamond Россия  
Дата: 29.06.17 20:12
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Здравствуйте, Vaynamond, Вы писали:


V>>Нет, я просто хочу вывести картинку на кнопке (совместно с текстом).


AG>Кстати, а может просто BM_SETIMAGE ?


А вот это мысль...
Судя по табличке, в зависимости от комбинации BS_BITMAP/BM_SETIMAGE можно выводить картинку + текст в разных комбинациях.

P.S.: Сейчас попробовал, облом: выводит картинку вместе с фоном (как и DrawState)
Отредактировано 30.06.2017 7:35 Vaynamond . Предыдущая версия .
Re[4]: BS_OWNERDRAW и DrawState
От: Vaynamond Россия  
Дата: 29.06.17 20:17
Оценка:
Здравствуйте, 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 — вроде кнопка получается адекватная.
Re[9]: BS_OWNERDRAW и DrawState
От: CEMb  
Дата: 30.06.17 02:16
Оценка: 8 (1)
Здравствуйте, 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 (я так всегда делаю)
Re[5]: BS_OWNERDRAW и DrawState
От: Alexander G Украина  
Дата: 30.06.17 05:34
Оценка:
Здравствуйте, Vaynamond, Вы писали:

V>Тут такой вопрос возник: при отображении нормальной кнопки все просто. А когда кнопка задизейблена ?

V>У меня сейчас проблема именно с выводом задизейбленой кнопки.

В случае NM_CUSTOMDRAW на стадии CDDS_POSTPAINT всё уже нарисовано за нас, включая и дизейбл:

// ...

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
    ON_NOTIFY(NM_CUSTOMDRAW, IDOK, OnCustomDrawOkButton)
END_MESSAGE_MAP()

// ...

void CAboutDlg::OnCustomDrawOkButton(NMHDR* nmhdr, LRESULT* result)
{
    NMCUSTOMDRAW* ncd = reinterpret_cast<NMCUSTOMDRAW*>(nmhdr);
    switch ( ncd->dwDrawStage )
    {
    case CDDS_PREPAINT:
        *result = CDRF_NOTIFYPOSTPAINT;
        return;

    case CDDS_POSTPAINT:
        // Рисуем поверх уже нарисованной кнопки
        // ... 
        return;
    }
}


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* функциями мороки больше.
Русский военный корабль идёт ко дну!
Re[6]: BS_OWNERDRAW и DrawState
От: Vaynamond Россия  
Дата: 30.06.17 07:22
Оценка:
Здравствуйте, Alexander G, Вы писали:

V>>Рисовать кнопку именно через DrawFrameControl ? Я сейчас использую DrawEdge — вроде кнопка получается адекватная.


AG>Через DrawFrameControl можно адекватно рисовать разные контролы (типа галочек и стрелочек) в разных состояниях.

AG>В частности, для кнопки не надо явно задавать направление и ширину выступа.

Я за основу брал пример из CodeGuru, так там еще более замороченный алгоритм: если кнопка нажата, она рисуется
с помощью FrameRect, а в остальных случаях — через DrawFrameControl.
Re[7]: BS_OWNERDRAW и DrawState
От: CEMb  
Дата: 30.06.17 07:31
Оценка:
Здравствуйте, Vaynamond, Вы писали:

AG>>Через DrawFrameControl можно адекватно рисовать разные контролы (типа галочек и стрелочек) в разных состояниях.

AG>>В частности, для кнопки не надо явно задавать направление и ширину выступа.

V>Я за основу брал пример из CodeGuru, так там еще более замороченный алгоритм: если кнопка нажата, она рисуется

V>с помощью FrameRect, а в остальных случаях — через DrawFrameControl.

А там у примера дата какая стоит?
CodeGuru хороший портал, удобный, с примерами, вот только жаль, что не популярный
я оттуда в своё время тоже код таскал
Re[6]: BS_OWNERDRAW и DrawState
От: Vaynamond Россия  
Дата: 30.06.17 07:56
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>В случае NM_CUSTOMDRAW на стадии CDDS_POSTPAINT всё уже нарисовано за нас, включая и дизейбл:


Сейчас стал смотреть, как пару лет назад панель инструментов делал на основе ReBar'а, так там картинки передаются
через ImageList. Собственно, вопрос: с кнопками такой вариант не прокатит ?
Смущает то, что есть для добавления BMP-файла макросы Add/AddMasked, для добавления ICO-файла макрос AddIcon,
а для получения — только GetIcon. Или прямо выводить с помощью ImageList_Draw ?
Re[8]: BS_OWNERDRAW и DrawState
От: Vaynamond Россия  
Дата: 30.06.17 08:57
Оценка:
Здравствуйте, CEMb, Вы писали:

CEM>Здравствуйте, Vaynamond, Вы писали:


AG>>>Через DrawFrameControl можно адекватно рисовать разные контролы (типа галочек и стрелочек) в разных состояниях.

AG>>>В частности, для кнопки не надо явно задавать направление и ширину выступа.

V>>Я за основу брал пример из CodeGuru, так там еще более замороченный алгоритм: если кнопка нажата, она рисуется

V>>с помощью FrameRect, а в остальных случаях — через DrawFrameControl.

CEM>А там у примера дата какая стоит?

CEM>CodeGuru хороший портал, удобный, с примерами, вот только жаль, что не популярный
CEM>я оттуда в своё время тоже код таскал

На исходнике декабрь 2002.
Re[10]: BS_OWNERDRAW и DrawState
От: Vaynamond Россия  
Дата: 30.06.17 09:02
Оценка: 1 (1)
Здравствуйте, CEMb, Вы писали:

CEM>По теме: я бы открыл картинку в редакторе и сделал 32-битную с альфой, потом BM_SETIMAGE (я так всегда делаю)

Это не наш метод
Если серьезно, уже сложилось исторически, что все картинки у нас (в нашем проекте) обычный 24-битный BMP.
В принципе, сейчас первый раз столкнулся с проблемой вывода картинки — все остальное выводится без проблем.

P.S.: Короче, выкрутился через ImageList. Добавляю туда BMP-шку с маской RGB(255, 0, 255), а в WM_DRAWITEM дергаю
ImageList_GetIcon(..., ILD_TRANSPARENT) и скармливаю полученный хендл функции DrawState. В итоге корректно выводится
и штатная картинка, и задизейбленая.
Отредактировано 30.06.2017 13:23 Vaynamond . Предыдущая версия .
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.