Blog. Just Blog

Гиперссылки в диалоговых окнах на Ассемблере

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Создание текстовой гиперссылки в диалоговом окне, казалось бы, простая задача. Но дело в том, что в Windows по умолчанию нет элементов диалоговых окон, которые бы выполняли роль гиперссылки. Готовых решений на FASM тоже не нашлось, значит придется создавать такой элемент самостоятельно. Сперва определимся с задачами, что нам надо сделать. Должен получиться элемент диалогового окна в виде текста определенного цвета, при наведении на который курсор должен менять свою форму, а цвет изменяться на подсвеченный. При клике на такой элемент должна открываться заданная ссылка. Задачи ясны, начнем их решать. Сперва выберем элемент диалоговых окон из списка стандартных, который и будет использоваться в качестве гиперссылки. Сразу же приходит на ум STATIC. По умолчанию элемент класса STATIC полностью оправдывает свое название и не реагирует практически ни на какие сообщения. Чтобы STATIC принимал движение курсора и нажатия клавиш мышки, его надо описать в ресурсах с флагом стилей SS_NOTIFY.

А как отследить движение курсора только над нашей гиперссылкой? Тут нам на помощь придет такая полезная вещь, как субклассирование. Суть субклассирования проста. С каждым окном связан указатель на оконную процедуру, которая обрабатывает сообщения Windows. Когда система получает сообщение, предназначенное для некоторого окна, она находит адрес оконной процедуры этого окна и вызывает ее. При субклассировании мы заменяем эту процедуру нашей и сохраняем указатель на старую процедуру, чтобы можно было передать ей сообщения для дальнейшей обработки. Это делается функцией SetWindowLong с индексом GWL_WNDPROC на этапе инициализации главного окна:
  1.         ...
  2.         ; Получить хэндл нашего STATIC'а
  3.         invoke  GetDlgItem,[hwnddlg],ID_LINK
  4.         ; Субклассировать гиперссылку и установить собственный
  5.         ; обработчик для STATIC'а
  6.         invoke  SetWindowLong,eax,GWL_WNDPROC,WindowProc
  7.         ; Сохранить адрес предыдущего обработчика
  8.         mov     [OldWndProc],eax
  9.         ...
Теперь напишем процедуру обработки. Тут важно понять основной принцип: при сообщениях, которые мы подавляем или обрабатываем самостоятельно, процедура должна возвращать FALSE, как будто бы их вообще не было. Если сообщение не обрабатывается или оно было модифицировано нашим обработчиком, то его обязательно надо передавать функцией CallWindowProc предыдущему обработчику, адрес которого сохранен при субклассировании. Это можно посмотреть на примере обработчика нашей гиперссылки.
  1. ;------------------------------------------------------------
  2. ; Наша собственная процедура обработки дочернего окна STATIC
  3. ;------------------------------------------------------------
  4. proc WindowProc hwnddlg:DWORD,msg:DWORD,wparam:DWORD,lparam:DWORD
  5.         cmp     [msg],WM_SETCURSOR      ; Курсор над ссылкой
  6.         je      .cursor_over_hyperlink
  7.         cmp     [msg],WM_LBUTTONDOWN    ; Нажатие мышкой на ссылке
  8.         je      .open_link
  9.  
  10.         ; Передать управление предыдущему обработчику
  11.         invoke  CallWindowProc,[OldWndProc],[hwnddlg],[msg],[wparam],[lparam]
  12.         ret
  13. .cursor_over_hyperlink:
  14.         ; Загрузить и установить курсор в виде руки
  15.         invoke  LoadCursor,0,IDC_HAND
  16.         invoke  SetCursor,eax
  17.         jmp     .finish
  18. .open_link:
  19.         ; Открыть ссылку
  20.         invoke  ShellExecute,[hwnddlg],szOpen,szLink,NULL,NULL,SW_SHOW
  21. .finish:
  22.         xor     eax,eax
  23.         ret
  24.  
  25. szOpen  db      'open',0                        ; Команда открытия
  26. szLink  db      'http://www.manhunter.ru',0     ; Ссылка на сайт
  27.  
  28. endp
Обрабатывается движение курсора над элементом и клик по нему левой кнопкой мыши. Все остальные сообщения без изменения передаются сохраненному предыдущему обработчику. Оставим реализацию гиперссылки через элемент STATIC на этом этапе и выберем для следующего примера какой-нибудь другой. Пусть это будет элемент класса EDIT. В сегменте данных добавляются новые переменные:
  1. section '.data' data readable writeable
  2.  
  3. hHyper          dd ?    ; Хэндл гиперссылки
  4. hBrushBack      dd ?    ; Хэндл кисточки
  5. sscolor         dd ?    ; Цвет закраски
  6.  
  7. clrMain         =     0FF0000h  ; Обычный цвет ссылки (синий)
  8. clrActive       =     00000FFh  ; Цвет активной ссылки (красный)
В инициализацию главного окна добавляется следующий код:
  1.         ...
  2.         ; Получить хэндл кисточки основного цвета окна
  3.         invoke  GetSysColor,COLOR_BTNFACE
  4.         invoke  CreateSolidBrush,eax
  5.         mov     [hBrushBack],eax
  6.  
  7.         ; Установить обычный цвет гиперссылки
  8.         mov     [sscolor],clrMain
  9.  
  10.         ; Получить хэндл нашего EDIT'а
  11.         invoke  GetDlgItem,[hwnddlg],ID_LINK
  12.         mov     [hHyper],eax
  13.         ...
Хэндл кисточки основного цвета окна нужен для отрисовки фонового цвета EDIT. Цвет элемента устанавливается по сообщению WM_CTLCOLOREDIT, но в обработчике надо обрабатывать только наш EDIT, остальные пропускать:
  1.         ...
  2.         cmp     [msg],WM_CTLCOLOREDIT
  3.         je      .set_color_edit
  4.         ...
  5. .set_color_edit:
  6.         ; Обрабатывается наш EDIT?
  7.         mov     eax,[hHyper]
  8.         cmp     [lparam],eax
  9.         je      @f
  10.         ; Нет, пропустить
  11.         xor     eax,eax
  12.         jmp     .finish
  13. @@:
  14.         ; Установить цвет текста ссылки
  15.         invoke  SetTextColor,[wparam],[sscolor]
  16.         ; Установить режим заднего фона на прозрачный
  17.         invoke  SetBkMode,[wparam],TRANSPARENT
  18.         ; Установить цвет EDIT как основной цвет окна
  19.         mov     eax,[hBrushBack]
  20.         jmp     .finish
В обработчике субклассированного элемента добавляется изменение цвета при наведении курсора на ссылку. Обновление и перерисовка гиперссылки с новым цветом выполняется функцией InvalidateRect, но сама обработка перерисовки выполняется в главном окне.
  1. ;------------------------------------------------------------
  2. ; Наша собственная процедура обработки дочернего окна EDIT
  3. ;------------------------------------------------------------
  4. proc WindowProc hwnddlg:DWORD,msg:DWORD,wparam:DWORD,lparam:DWORD
  5.         cmp     [msg],WM_SETCURSOR      ; Курсор над ссылкой
  6.         je      .cursor_over_hyperlink
  7.         cmp     [msg],WM_LBUTTONDOWN    ; Нажатие мышкой на ссылке
  8.         je      .open_link
  9.  
  10.         ; Передать управление предыдущему обработчику
  11.         invoke  CallWindowProc,[OldWndProc],[hwnddlg],[msg],[wparam],[lparam]
  12.         ret
  13. .cursor_over_hyperlink:
  14.         ; Загрузить и установить курсор в виде руки
  15.         invoke  LoadCursor,0,IDC_HAND
  16.         invoke  SetCursor,eax
  17.         ; Установить цвет текста ссылки
  18.         mov     [sscolor],clrActive
  19.         ; Перерисовать EDIT в новом цвете
  20.         invoke  InvalidateRect,[hHyper],NULL,TRUE
  21.         jmp     .finish
  22. .open_link:
  23.         ; Открыть ссылку
  24.         invoke  ShellExecute,[hwnddlg],szOpen,szLink,NULL,NULL,SW_SHOW
  25.         ; Установить цвет текста ссылки
  26.         mov     [sscolor],clrMain
  27.         ; Перерисовать EDIT в новом цвете
  28.         invoke  InvalidateRect,[hHyper],NULL,TRUE
  29. .finish:
  30.         xor     eax,eax
  31.         ret
  32.  
  33. szOpen  db      'open',0                        ; Команда открытия
  34. szLink  db      'http://www.manhunter.ru',0     ; Ссылка на сайт
  35.  
  36. endp
Когда курсор выходит за границы гиперссылки, надо возвращать ее цвет в исходный. Это придется выполнять в главном окне, обрабатывая движение курсора над ним.

UPD: Тут камрад Zummenix подсказал как корректно сделать STATIC цветным. Спасибо! Перезалил примеры, статью править пока не буду.

Есть еще варианты создания гиперссылки в диалоговых окнах через RichEdit, внедренный HTML и всякие посторонние компоненты, но они тут рассматриваться не будут. В приложении два примера диалоговых окон с текстовой гиперссылкой, реализованной через элементы классов STATIC и EDIT.

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

Text.HyperLink.Demo.zip (8,163 bytes)


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

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

Комментарии

Отзывы посетителей сайта о статье
Alex (08.12.2023 в 11:22):
В ComCtl32.dll версии 6 определен элемент управления SysLink.
ManHunter (01.10.2022 в 19:02):
Когда люди придумали деньги, количество нерешаемых задач значительно уменьшилось. Пара-тройка сотен баксов упростит решение.
Анна (01.10.2022 в 16:07):
Добрый день, а можете подсказать, как мне реализовать эту задачу?
Скачать 3 иконки и 2 курсора. Реализовать приложение с использованием TabStip с 3 закладками. При переходе на другую закладку нужно поменять иконку. Каждая закладка должна иметь другое оконное наполнение. При наведении мышкой на текстовое поле устанавливается 1 курсор, на кнопку 2-й. При движении по другому полю окна курсор стандартный.
начали учить ассемблер на парах, но я очень мало понимаю(
ManHunter (10.07.2009 в 17:25):
Перезалил примеры с цветым статиком. Zummenix, спасибо!
ManHunter (10.07.2009 в 16:06):
Кинь, интересно посмотреть. У меня что-то так и не получилось.
Zummenix (10.07.2009 в 16:02):
Делал HyperLink на статике, цвет текста прекрасно меняется через SetTextColor, могу скинуть исходник, если нужно :)

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

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

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