Blog. Just Blog

Как добавить иконку щита UAC на кнопку

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Начиная с Windows Vista, в интерфейсе системы на некоторых элементах управления появился значок в виде щита. Он означает, что при взаимодействии с таким элементом у пользователя будут запрошены повышенные права доступа. Если ваша программа выполняет действия, которые требуют повышенных прав, то хорошим тоном будет тоже отмечать специальной иконкой элементы управления, запускающие такие функции. Но совсем не обязательно таскать иконку в ресурсах или в каких-то отдельных файлах, тем более, что на разных системах она выглядит по-разному. Все делается очень просто, достаточно отправить нужной кнопке сообщение BCM_SETSHIELD и система сама дополнит кнопку иконкой щита, принятой в данной версии Windows. Если lParam сообщения равен TRUE, то иконка щита добавляется, а если FALSE, то, соответственно, удаляется.
  1.         BCM_SETSHIELD = 0x160C
  2.  
  3.         ; Установить иконку на кнопку
  4.         invoke  SendDlgItemMessage,[hwnddlg],ID_BTN1,BCM_SETSHIELD,0,TRUE
Узнать наличие иконки щита на кнопке можно при помощи сообщения BM_GETIMAGE. Точнее, так можно определить наличие иконки вообще, а не конкретно щита. Если сообщение вернуло 0, то никакая иконка на кнопке не отображается.
  1.         ; Какая-то иконка на кнопке уже есть?
  2.         invoke  SendDlgItemMessage,[hwnddlg],ID_BTN1,BM_GETIMAGE,IMAGE_ICON,0
  3.         or      eax,eax
  4.         jnz     @f
  5.         ; Иконки нет
  6.         ...
  7. @@:
  8.         ; Иконка есть
  9.         ...
В официальной документации сказано, что единственными элементами управления, на которые таким образом можно навесить значок щита, являются кнопки и командные ссылки. Но никто не запрещает загрузить изображение щита как обычную иконку и затем использовать ее хэндл. Иконка загружается с небольшим подвыподвертом - через функцию LoadIconWithScaleDown. Загруженную иконку можно установить в заголовок окна, на STATIC, в заголовок вкладки, точно так же на кнопку или на любой другой элемент диалогового окна, который поддерживает отображение HICON.
  1.         IDI_SHIELD    = 0x7F06
  2.  
  3.         ; Загрузить иконку щита
  4.         invoke  GetSystemMetrics,SM_CXSMICON
  5.         invoke  LoadIconWithScaleDown,0,IDI_SHIELD,eax,eax,hShieldIcon
  6.         ; [hShieldIcon] --> хэндл иконки щита
  7.  
  8.         ; Установить иконку на кнопку
  9.         invoke  SendDlgItemMessage,[hwnddlg],ID_BTN2,BM_SETIMAGE,\
  10.                 IMAGE_ICON,[hShieldIcon]
  11.         ; Установить иконку в заголовок окна
  12.         invoke  SendMessage,[hwnddlg],WM_SETICON,ICON_SMALL,[hShieldIcon]
  13.         ; Установить иконку на STATIC
  14.         invoke  SendDlgItemMessage,[hwnddlg],ID_STAT,STM_SETIMAGE,\
  15.                 IMAGE_ICON,[hShieldIcon]
Важное замечание. Чтобы программа могла использовать сообщение BCM_SETSHIELD и функцию LoadIconWithScaleDown, она должна быть скомпилирована с манифестом, в котором заявлена поддержка динамической библиотеки comctl32.dll версии 6.

Также иконку щита можно добавить на элементы окон, открытых при помощи функции MessageBox, MessageBoxEx или MessageBoxIndirect. Для этого надо установить хук на создание окна, как рассказано в этой статье, а в обработчике выполнять различные действия с элементами окна сообщения.
  1.         ; Получить хэндл текущего потока
  2.         invoke  GetCurrentThreadId
  3.         ; Установить перехватчик событий
  4.         invoke  SetWindowsHookEx,WH_CBT,MBHookProc,NULL,eax
  5.         mov     [hMBHook],eax
  6.  
  7.         ; Открыть MessageBox с кнопками Да/Нет
  8.         mov     [MsgBoxParams.cbSize],sizeof.MSGBOXPARAMS
  9.         mov     eax,[hwnddlg]
  10.         mov     [MsgBoxParams.hwndOwner],eax
  11.         invoke  GetModuleHandle,0
  12.         mov     [MsgBoxParams.hInstance],eax
  13.         mov     [MsgBoxParams.lpszText],szMess
  14.         mov     [MsgBoxParams.lpszCaption],szTitle
  15.         mov     [MsgBoxParams.dwStyle],MB_USERICON+MB_YESNO
  16.         mov     [MsgBoxParams.lpszIcon],0
  17.         invoke  MessageBoxIndirect,MsgBoxParams
  18.  
  19.         ; Снять перехватчик
  20.         invoke  UnhookWindowsHookEx,[hMBHook]
Точно так же можно установить иконку щита в заголовок окна сообщения или добавить ее к одной или нескольким кнопкам, отправляя BCM_SETSHIELD по стандартным идентификаторам этих кнопок.
  1. proc MBHookProc nCode:DWORD,wParam:DWORD,lParam:DWORD
  2.         locals
  3.                 hIcon dd ?
  4.         endl
  5.  
  6.         ; Сохранить все регистры
  7.         pusha
  8.  
  9.         cmp     [nCode],HCBT_ACTIVATE
  10.         jne     @f
  11.  
  12.         ; Установить иконку окна
  13.         invoke  SendMessage,[wParam],WM_SETICON,ICON_SMALL,[hShieldIcon]
  14.         ; Установить иконку щита на кнопку Yes
  15.         invoke  SendDlgItemMessage,[wParam],IDYES,BCM_SETSHIELD,0,TRUE
  16.  
  17.         ; Загрузить иконку щита 32х32
  18.         lea     eax,[hIcon]
  19.         invoke  LoadIconWithScaleDown,0,IDI_SHIELD,32,32,eax
  20.         ; Установить ее вместо пользовательской иконки
  21.         invoke  SendDlgItemMessage,[wParam],14h,STM_SETIMAGE,IMAGE_ICON,[hIcon]
  22.  
  23.         ; Восстановить регистры
  24.         popa
  25.  
  26.         xor     eax,eax
  27.         ret
  28. @@:
  29.         ; Восстановить регистры
  30.         popa
  31.  
  32.         ; Передать управление следующему обработчику
  33.         invoke  CallNextHookEx,[hMBHook],[nCode],[wParam],[lParam]
  34.         ret
  35. endp
В приложении пример программы с исходным текстом, которая добавляет иконку щита UAC на кнопки и другие элементы диалогового окна.

Пример программы с исходным текстом (FASM)Пример программы с исходным текстом (FASM)

Shield.Icon.Demo.zip (4,019 bytes)


Поделиться ссылкой ВКонтакте
Просмотров: 1156 | Комментариев: 1

Метки: Assembler, иконки
Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
ManHunter (11.12.2020 в 15:25):
Добавил информацию, как определить наличие иконки на кнопке. Архив обновлен.

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.1 сек. / MySQL: 2 (0.0066 сек.) / Память: 4.5 Mb
Наверх