2010-05-04 2 views
0

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

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

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

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

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

Хавьер

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

ответ

1

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

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

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

+0

Пожалуйста, обратите внимание на мою заметку в исходном вопросе. И спасибо за вашу помощь. –

1

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

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

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

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

Windows_UI_source.zip

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

+0

Я посмотрел на ваш код, но я не вижу, как это решает мою проблему. В итоге вы вызываете DrawThemeBackground с состоянием PBS_HOT и рисуете обычную (не нажатую) кнопку с золотой границей (горячее состояние). Мне нужен способ нарисовать нажатое (PBS_PRESSED) состояние с золотой границей (горячее состояние). Большое спасибо в любом случае. –

+0

Моя ошибка: я неправильно понял ваш вопрос. Я не думаю, что есть способ сделать DrawThemeBackground() делать то, что вы хотите: все, что я могу предложить, - это нарисовать фоном и альфа-смешение в «горячем» прямоугольнике состояния самостоятельно. Если вы всегда так называли «горячий» прямоугольник, вы, вероятно, могли бы получить сносный эффект. – DavidK

+0

Это что-то похожее на то, что я сделал. Фактически эффект неплохой, без использования AlphaBlend (я дам ему попробовать, если кто-то жалуется!). К сожалению, я уже принял свой ответ, когда увидел ваш комментарий, и я не могу снять свое согласие. Я бы принял ваш ответ иначе. Спасибо. –

Смежные вопросы