Пользовательская кнопка рисования с использованием uxtheme.dll

Я реализовал свою пользовательскую кнопку, унаследованную от CButton и нарисовав ее, используя uxtheme.dll (DrawThemeBackground с BP_PUSHBUTTON).

Все работает нормально, но у меня есть два статуса (Нормальный и Отжатый), статус Горячего одинаковый. Это означает, что когда пользователь наводит курсор на кнопку, она рисуется одинаково, независимо от состояния кнопки (нажата или нет).

Это немного сбивает с толку пользователя, и я хотел бы изменить способ отображения кнопки в состоянии "Нажатие и горячее". Кто-нибудь знает способ?

Я также думал о настройке всего чертежа, но кнопки используют градиенты, границы, тени и т. Д. Поэтому нелегко добиться того же внешнего вида и ощущения, рисуя все самостоятельно. Есть ли способ найти исходный код DLL или знать, как это сделать?

Заранее спасибо.

Хавьер

Примечание: я думаю, что смог бы достичь того, что хочу, используя CMFCButton и переопределив метод OnDraw. Позвольте элементу управления нарисовать кнопку на OnDrawBorder и затем нарисовать внутреннюю кнопку самостоятельно. Но мне нужно знать, как элемент управления рисует внутреннюю кнопку при нажатии. Это градиент, и я не могу догадаться, как это делается. У кого-нибудь есть подсказка?

3 ответа

Решение

Я наконец понял, как добиться того, что я хочу сделать. Это действительно легко.

Я использую два вызова DrawThemeBackground. Первый с PBS_PRESSED, а второй с состоянием PBS_HOT. Затем я делаю ExcludeClipRect, чтобы избежать рисования по центру кнопки.

Что-то вроде этого:

        DrawThemeBackground(    hTheme,
                                pCustomDraw->hdc, 
                                BP_PUSHBUTTON,
                                PBS_PRESSED,
                                &pCustomDraw->rc, 
                                NULL);

        CDC *pDC = CDC::FromHandle(pCustomDraw->hdc);

        CRect rectClient;
        GetClientRect(rectClient);
        CRect rectInternal = rectClient;

        rectInternal.DeflateRect(4,4);
        pDC->SelectClipRgn(NULL);
        pDC->ExcludeClipRect(&rectInternal);

        DrawThemeBackground(    hTheme,
                                pCustomDraw->hdc, 
                                BP_PUSHBUTTON,
                                PBS_HOT,
                                &pCustomDraw->rc, 
                                NULL);

        pDC->SelectClipRgn(NULL);

Конечно, это не весь код, но я думаю, что этого достаточно, чтобы высказать свою точку зрения.

Благодарю.

В ответ на ваш второй вопрос, если вы производите от CMFCButton вместо CButton Вы можете переопределить OnDraw() или же OnDrawText() вместо обычного DrawItem(), Таким образом, фон кнопки по умолчанию будет нарисован, а затем ваш код рисования будет выполнен.

Единственный способ, которым я знаю, чтобы по-настоящему справиться с этим, - это использовать "пользовательскую ничью", а не "ничью владельца". Настраиваемое рисование появилось в Windows 2000, но используется только кнопочными элементами управления с comctrl32 6.0 (начиная с Windows XP и далее), не очень четко задокументировано и не является чем-то, что MFC старается поддерживать.

В любом случае, хорошая особенность пользовательского рисования заключается в том, что он позволяет вам подключаться к различным точкам процесса рисования, в отличие от рисования владельцем, что заставляет вас иметь дело со всем этим. Посмотрите в MSDN сообщение-уведомление NM_CUSTOMDRAW.

Для другой части вашей проблемы, обнаружение "горячего" состояния, самый простой способ сделать это - использовать сообщения WM_MOUSEMOVE и функцию TrackMouseEvent(), чтобы отслеживать, находится ли мышь над вашей кнопкой.

К сожалению, это немного расплывчатый ответ: объем кода, который вам необходим для демонстрации кнопки, использующей пользовательское рисование, слишком велик для ввода в эти поля для ответов! У меня есть проект, который демонстрирует такие приемы, используя настраиваемую кнопку рисования (возврат к рисованию владельца в старых версиях Windows), которая добавляет небольшую стрелку к кнопке. Вы можете взглянуть на исходный код, получив

Windows_UI_source.zip

Откройте его и посмотрите на класс "DropArrowButton". Важным битом является обработчик OnCustomDraw() и его вспомогательная функция DrawControl(): они вызываются на различных этапах рисования кнопок и используют UxTheme для соответствующего рисования элемента управления.

Другие вопросы по тегам