Blog. Just Blog

Работа с контролом SysTabControl32 на Ассемблере

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Работа с контролом SysTabControl32 на Ассемблере
Работа с контролом SysTabControl32 на Ассемблере

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

Основу для вкладок сделать очень просто. Создаете контейнер, то есть сам элемент SysTabControl32, он или описывается в ресурсах, или создается динамически. Получаете его хэндл, заполняете структуру TC_ITEM, после чего поочередно добавляете нужное количество вкладок, отправляя контейнеру сообщения TCM_INSERTITEM.
  1.         ; Получить хэндл контейнера вкладок
  2.         invoke  GetDlgItem,[hwnddlg],TAB_MAIN
  3.         mov     [hTab],eax
  4.  
  5.         ; Инициализация структуры вкладок
  6.         mov     [TabCtrlItem.mask],TCIF_TEXT
  7.         mov     [TabCtrlItem.lpReserved1],0
  8.         mov     [TabCtrlItem.lpReserved2],0
  9.         mov     [TabCtrlItem.iImage],-1
  10.         mov     [TabCtrlItem.lParam],0
  11.         ; Максимальный размер текста
  12.         mov     [TabCtrlItem.cchTextMax],64
  13.  
  14.         ; Добавить первую вкладку
  15.         mov     [TabCtrlItem.pszText],stitle1
  16.         invoke  SendMessage,[hTab],TCM_INSERTITEM,0,TabCtrlItem
  17.  
  18.         ; Добавить вторую вкладку
  19.         mov     [TabCtrlItem.pszText],stitle2
  20.         invoke  SendMessage,[hTab],TCM_INSERTITEM,1,TabCtrlItem
  21.  
  22.         ; Добавить третью вкладку
  23.         mov     [TabCtrlItem.pszText],stitle3
  24.         invoke  SendMessage,[hTab],TCM_INSERTITEM,2,TabCtrlItem
Но просто добавлять вкладки никакого смысла нет, поэтому в контейнер надо добавить дочерними окнами диалоги, в которых и содержится вся начинка вкладок. Обработчики этих дочерних окон ничем не отличаются от обычных обработчиков диалогов. Хэндлы добавленных окон надо сохранить в каком-нибудь массиве, чтобы в дальнейшем была возможность ими манипулировать. Осталось скрыть окна всех ненужных вкладок, оставить только нужное и сохранить индекс открытой вкладки где-нибудь в локальной переменной. Если надо сразу показать вкладку с индексом, отличным от нуля, то контейнеру надо указать на это, отправив сообщение TCM_SETCURSEL.
  1.         ; Добавить диалоги и обработчики на каждую вкладку
  2.         invoke  CreateDialogParam,[hInstance],ID_SHEET1,[hTab],DialogOneProc,0
  3.         mov     [hTabDlg+0*4],eax
  4.         invoke  CreateDialogParam,[hInstance],ID_SHEET2,[hTab],DialogTwoProc,0
  5.         mov     [hTabDlg+1*4],eax
  6.         invoke  CreateDialogParam,[hInstance],ID_SHEET3,[hTab],DialogThreeProc,0
  7.         mov     [hTabDlg+2*4],eax
  8.  
  9.         ; Показать первую вкладку, остальные скрыть
  10.         invoke  ShowWindow,[hTabDlg+0*4],SW_SHOWDEFAULT
  11.         invoke  ShowWindow,[hTabDlg+1*4],SW_HIDE
  12.         invoke  ShowWindow,[hTabDlg+2*4],SW_HIDE
  13.  
  14.         ; Текущая вкладка - первая
  15.         mov     [SelTab],0
  16.         ; Установить текущую вкладку
  17.         invoke  SendMessage,[hTab],TCM_SETCURSEL,[SelTab],0
Вкладки создали, их содержимое создали, осталось сделать, чтобы это все работало как единое целое. С этим тоже никаких проблем. В обработчике главного окна, в котором находится контейнер SysTabControl32, надо добавить обработку сообщения WM_NOTIFY. При поступлении этого сообщения проверяем, что оно пришло от нужного нам контрола, затем проверяем, что уведомление относится к переключению вкладок. Дальше из нашей внутренней переменной получаем индекс текущей вкладки, по этому индексу получаем хэндл окна из массива, скрываем это окно, получаем индекс выбранной вкладки при помощи сообщения TCM_GETCURSEL, сохраняем его в переменную и показываем окно, соответствующее выбранной вкладке.
  1.         cmp     [msg],WM_NOTIFY
  2.         je      .tabproc
  3.         ...
  4.         ...
  5. .tabproc:
  6.         ; Обработчик переключения вкладок
  7.         cmp     [wparam],TAB_MAIN
  8.         jne     .processed
  9.  
  10.         ; Пришло уведомление о переключении вкладки?
  11.         mov     eax,[lparam]
  12.         cmp     [eax+NMHDR.code],TCN_SELCHANGE
  13.         jne     .processed
  14.  
  15.         ; Спрятать текущую вкладку
  16.         mov     eax,[SelTab]
  17.         invoke  ShowWindow,[hTabDlg+eax*4],SW_HIDE
  18.  
  19.         ; Получить выбранную вкладку
  20.         invoke  SendMessage,[hTab],TCM_GETCURSEL,0,0
  21.  
  22.         ; Текущая вкладка = новая вкладка
  23.         mov     [SelTab],eax
  24.  
  25.         ; Показать новую вкладку
  26.         invoke  ShowWindow,[hTabDlg+eax*4],SW_SHOWDEFAULT
Базовые техники освоили, теперь поговорим о прекрасном, то есть о стилизации. Очень здорово выглядят вкладки, на которых рядом с текстом расположены иконки. Делается это так же просто, управляющий код остается без изменений, дополнится только код инициализации контрола. Сперва создается список изображений, в котором будут храниться иконки для вкладок. Список изображений можно заполнять из ресурсов, из внешних файлов, но мне удобнее сделать это иконками из памяти. На самом деле способ не так важен, главное на выходе получить хэндл икноки HICON, который и будет добавлен в список при помощи функции ImageList_AddIcon. Заполненный список надо связать с контролом, отправив контейнеру SysTabControl32 сообщение TCM_SETIMAGELIST. После этого можно добавлять вкладки, указывая в поле iImage структуры TC_ITEM индекс изображения, которое появится в качестве иконки рядом с текстом. В параметр mask структуры также добавится флаг TCIF_IMAGE, сообщающий системе, что на вкладках планируется размещать не только текст, но и иконки.
  1.         ; Инициализация структуры вкладок
  2.         mov     [TabCtrlItem.mask],TCIF_TEXT + TCIF_IMAGE
  3.         mov     [TabCtrlItem.lpReserved1],0
  4.         mov     [TabCtrlItem.lpReserved2],0
  5.         mov     [TabCtrlItem.lParam],0
  6.         ; Максимальный размер текста
  7.         mov     [TabCtrlItem.cchTextMax],64
  8.  
  9.         ; Создать список изображений
  10.         invoke  ImageList_Create,16,16,ILC_COLOR32 + ILC_MASK,3,0
  11.         mov     [hImageList],eax
  12.  
  13.         ; Заполнить список иконками
  14.         stdcall LoadIconFromMemory,icon_1,16
  15.         invoke  ImageList_AddIcon,[hImageList],eax
  16.         stdcall LoadIconFromMemory,icon_2,16
  17.         invoke  ImageList_AddIcon,[hImageList],eax
  18.         stdcall LoadIconFromMemory,icon_3,16
  19.         invoke  ImageList_AddIcon,[hImageList],eax
  20.  
  21.         ; Связать список картинок с контролом
  22.         invoke  SendMessage,[hTab],TCM_SETIMAGELIST,0,[hImageList]
  23.  
  24.         ; Добавить первую вкладку
  25.         mov     [TabCtrlItem.pszText],stitle1
  26.         mov     [TabCtrlItem.iImage],0
  27.         invoke  SendMessage,[hTab],TCM_INSERTITEM,0,TabCtrlItem
  28.  
  29.         ; Добавить вторую вкладку
  30.         mov     [TabCtrlItem.pszText],stitle2
  31.         mov     [TabCtrlItem.iImage],1
  32.         invoke  SendMessage,[hTab],TCM_INSERTITEM,1,TabCtrlItem
  33.  
  34.         ; Добавить третью вкладку
  35.         mov     [TabCtrlItem.pszText],stitle3
  36.         mov     [TabCtrlItem.iImage],2
  37.         invoke  SendMessage,[hTab],TCM_INSERTITEM,2,TabCtrlItem
Добавим еще немного стилизации. Если элемент SysTabControl32 был создан со значением TCS_FIXEDWIDTH в стилях, то вы можете изменять ширину и высоту вкладок. Например, вот так задается высота 30 пикселов и ширина 90 пикселов:
  1.         ; Установить размер вкладок
  2.         invoke  SendMessage,[hTab],TCM_SETITEMSIZE,0,(30 shl 16 + 90)
Вся остальная стилизация SysTabControl32 в большинстве случаев задается прямо при создании контрола и настраивается соответствующими флагами, об их свойствах и значениях вы можете почитать в документации.

И еще немного стилизации, а точнее, динамики. Для того, чтобы в любой момент поменять заголовок и/или иконку вкладки, надо воспользоваться сообщением TCM_SETITEM. Его можно использовать, например, устанавливая на активную вкладку цветную иконку, а при уходе с вкладки заменяя ее на иконку в градациях серого. Или добавлять звездочку к названию изменившейся вкладки, как это делают некоторые текстовые редакторы. Или еще как-нибудь, в зависимости от решаемой задачи.
  1.         ; Указатель на строку нового заголовка
  2.         mov     [TabCtrlItem.pszText],stitle3x
  3.         ; Индекс новой иконки из ImageList
  4.         mov     [TabCtrlItem.iImage],3
  5.         ; Установить новую иконку и заголовок третьей вкладке
  6.         invoke  SendMessage,[hTab],TCM_SETITEM,2,TabCtrlItem
В приложении примеры программ с исходными текстами, которые создают окна с обычными вкладками и вкладками с иконками.

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

SysTabControl32.Demo.zip (11,752 bytes)


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

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

Комментарии

Отзывы посетителей сайта о статье
Mikl___ (27.04.2022 в 06:07):
Может быть кому-то и пригодится
Сказки дядюшки Римуса о х64--> Создание закладок
https://wasm.in/threads/skazki...#post-383774
Управляющие сообщения, Нотификационные сообщения, Стили элементов Tab Control, Иконки на Tab Control
https://wasm.in/threads/skazki...#post-383775
masm 64-бита
Nemo (20.08.2021 в 10:03):
Видимо это баг Winapi DialogBoxParam / CreateDialogParam. При создании диалога функциями DialogBoxIndirectParam / CreateDialogIndirectParam и установки стиля WS_EX_CONTROLPARENT SysTabControl32 и вкладкам, tabstop работает без хуков
ManHunter (16.08.2021 в 13:03):
Я в своей программе Hotkey Helper делал через хуки.
Nemo (16.08.2021 в 12:32):
При установке стилей WS_EX_CONTROLPARENT сhild window и SysTabControl32 VK_TAB работает только с control'ами основного окна и первым control child window.
Есть ли способ, кроме хуков, восстановить taborder вкладок ?
(диалоги MFC работают корректно)
ManHunter (01.11.2020 в 18:34):
Цитатачем интересней тема/пост - тем меньше комментариев и благодарностей

Как говорила одна из моих школьных учительниц, "если нет вопросов, значит или все понятно, или не понятно ничего".
GRAFik (01.11.2020 в 16:40):
ManHunter, огромное спасибо за интересную тему, которую, по-моему, в сети не так-то просто и найти, а на FASM'е так точно больше нигде не найдешь. Я помню, у Фроловых код на Си находил, да и то, то ли не весь или там какие-то ошибки(опечатки) были, не помню уже, но что-то я долго с ним разбирался. Может на тот момент у меня опыта поменьше было? ))

P.S. Заметил некую тенденцию: чем интересней тема/пост - тем меньше комментариев и благодарностей. Может это поварская тематика многих серьезных людей отпугивает и они боятся нарваться на очередной рецепт борща от ManHunter'а? ))
dark (01.11.2020 в 11:03):
красиво смотриться лайк

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

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

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