Пользовательская кнопка рисования с использованием uxtheme.dll - PullRequest
0 голосов
/ 04 мая 2010

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

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

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

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

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

Хавьер

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

Ответы [ 3 ]

1 голос
/ 11 мая 2010

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

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

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

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

Windows_UI_source.zip

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

1 голос
/ 12 мая 2010

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

Я использую два вызова 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);

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

Спасибо.

1 голос
/ 04 мая 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...