Что нового

GUICtrlOnHover - Обработка событии при наведении мышки

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 156
Репутация
2 329
AutoIt: 3.3.0.0+
Версия: 2.1
Категория: Элементы GUI
Описание: Позволяет установить обработчик на событие вызываемое при наведении курсора мышки над элементами GUI (OnHover)
Пример:
Код:
#include "GUICtrlOnHover.au3"

Opt("GUIOnEventMode", 1)

$Btn_Color = 0x7A9DD8
$Hover_Color = 0xFF0000 ;0x7AC5D8

$GUIMain = GUICreate("Letters Hovering Example", 570, 200)
GUISetOnEvent(-3, "Quit")

_CreateLetters_Proc(10, 60, 18, 20)

GUICtrlCreateButton("Close", 30, 120, 100, 30)
GUICtrlSetOnEvent(-1, "Quit")

GUICtrlSetFont(GUICtrlCreateLabel("Letter: ", 35, 170, 200, 20), 9, 800)
$Status_Label = GUICtrlCreateLabel("", 80, 171, 200, 20)
GUICtrlSetColor(-1, 0xFF0000)
GUICtrlSetFont(-1, 8.5, 800)

GUISetState()

While 1
    Sleep(100)
WEnd

Func _CreateLetters_Proc($iLeft, $Top, $Width=15, $Height=15)
	Local $iLeft_Begin = $iLeft
	Local $iAsc_Char = 64
	
	For $i = 0 To 25
		$iLeft_Begin += 20
		$iAsc_Char += 1
		GUICtrlCreateButton(Chr($iAsc_Char), $iLeft_Begin, $Top, $Width, $Height)
		
		_GUICtrl_OnHoverRegister(-1, "_Hover_Func", "_Leave_Hover_Func")
		GUICtrlSetOnEvent(-1, "_Letter_Events")
		GUICtrlSetBkColor(-1, $Btn_Color)
		GUICtrlSetFont(-1, 6)
	Next
EndFunc

Func _Letter_Events()
	MsgBox(64, "Pressed", "Letter = " & GUICtrlRead(@GUI_CtrlId))
EndFunc

Func _Hover_Func($iCtrlID)
	GUICtrlSetBkColor($iCtrlID, $Hover_Color)
	GUICtrlSetData($Status_Label, GUICtrlRead($iCtrlID))
	Beep(1000, 20)
EndFunc

Func _Leave_Hover_Func($iCtrlID)
	GUICtrlSetBkColor($iCtrlID, $Btn_Color)
	GUICtrlSetData($Status_Label, "")
EndFunc

Func Quit()
    Exit
EndFunc

Screenshot: N/A

Скачать: GUICtrl_SetOnHover.zip
(во вложениях старые версии).

Источник: CreatoR, http://www.autoitscript.com/forum/index.php?s=&showtopic=55120
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 702
Re: GUICtrlSetOnHover - Обработка событии при навидении

Отлично, CreatoR. Спасибо. Я давно ждал этот UDF здесь.

+1

:smile:
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 702
Re: GUICtrlSetOnHover - Обработка событии при навидении

Обнаружил одну проблему. Если нажать кнопку мыши вне элемента и затем, не отпуская кнопки, подвести к любому элементу, то срабатывает вызов функции для нажатия. Мог бы ты это пофиксить?

:-\
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 156
Репутация
2 329
Re: GUICtrlSetOnHover - Обработка событии при навидении

Yashied [?]
Если нажать кнопку мыши вне элемента и затем, не отпуская кнопки, подвести к любому элементу, то срабатывает вызов функции для нажатия
Это действительно проблема, и простого решения я пока не вижу. Есть идеи как различить нажатие на кнопке и в другом месте (я уже молчу про нажатие на другом элементе, на который тоже задан OnHover)?
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 156
Репутация
2 329
Re: GUICtrlSetOnHover - Обработка событии при навидении

Нашёл решение! :whistle: Правда тут нужно будет задействовать WM_COMMAND и WM_LBUTTONUP...
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 156
Репутация
2 329
Re: GUICtrlSetOnHover - Обработка событии при навидении

Мда, оказалось сложнее чем я думал. Придётся ставить Mouse Hook... Нет не придётся (тем более с ним свои проблемы), всё же обошлось дело одними WM_... сообщениями.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 702
Re: GUICtrlSetOnHover - Обработка событии при наведении

Как тебе такой вариант?

Код:
#Include <Constants.au3>
#Include <WinAPIEx.au3>
#Include <WindowsConstants.au3>

Global Const $WM_MOUSELEAVE = 0x02A3
;Global Const $WM_MOUSEMOVE = 0x0200

Global $Hover = False

$hForm = GUICreate('MyGUI', 400, 400)
$Button = GUICtrlCreateButton('Exit', 165, 366, 70, 23)

$hButton = GUICtrlGetHandle($Button)
$hDll = DllCallbackRegister('_WinProc', 'ptr', 'hwnd;uint;wparam;lparam')
$pDll = DllCallbackGetPtr($hDll)
$hProc = _WinAPI_SetWindowLong($hButton, $GWL_WNDPROC, $pDll)

GUISetState()

Do
Until GUIGetMsg() = -3

Func _WinProc($hWnd, $iMsg, $wParam, $lParam)
    Switch $iMsg
        Case $WM_MOUSEMOVE
            If Not $Hover Then
                ConsoleWrite('Hover' & @CR)
                $Hover = 1
            EndIf
        Case $WM_MOUSELEAVE
            ConsoleWrite('Leave' & @CR)
            $Hover = 0
    EndSwitch
    Return _WinAPI_CallWindowProc($hProc, $hWnd, $iMsg, $wParam, $lParam)
EndFunc   ;==>_WinProc

Func OnAutoItExit()
    _WinAPI_SetWindowLong($hButton, $GWL_WNDPROC, $hProc)
    DllCallbackFree($hDll)
EndFunc   ;==>OnAutoItExit
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 702
Re: GUICtrlSetOnHover - Обработка событии при наведении

:(

Здесь тоже есть много проблем.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 702
Re: GUICtrlSetOnHover - Обработка событии при наведении

Можно еще попробывать использовать _IsPressed() внутри функции таймера и ввести глобальный флаг, который будет однозначно (10 мс - ?) показывать состояние клавиши мыши. Получиться своего рода замена Mouse Hook. Останется только проверить этот флаг перед вызовом пользовательской функции.

Код:
$LeftButtonDown = _IsPressed('01')
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 156
Репутация
2 329
Re: GUICtrlSetOnHover - Обработка событии при наведении

Yashied [?]
Можно еще попробывать использовать _IsPressed() внутри функции таймера
Мне не хотелось бы нагружать скрипт постоянным (и лишним) вызовом Dll'ок... Решение у меня уже есть, вопрос насколько UDF после этого будет конфликтовать с другими скриптами, в силу использования WM сообщении?
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 702
Re: GUICtrlSetOnHover - Обработка событии при наведении

Мне не терпится посмотреть на твое решение.

:laugh:
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 156
Репутация
2 329
Re: GUICtrlSetOnHover - Обработка событии при наведении

Yashied [?]
Мне не терпится посмотреть на твое решение
Примерно так:

В переменные (в начало) добавляем:
Код:
Global $iLAST_PRIMARYDOWN_CTRLID				= 0

Global Const $__GUICtrl_SetOnHover_WM_COMMAND		= 0x0111
Global Const $__GUICtrl_SetOnHover_WM_LBUTTONDOWN	= 0x0201


В функцию _GUICtrl_SetOnHover под условие «If $pTimerProc = 0 Then» добавляем:
Код:
GUIRegisterMsg($__GUICtrl_SetOnHover_WM_COMMAND, "__GUICtrl_SetOnHover_WM_COMMAND")
		GUIRegisterMsg($__GUICtrl_SetOnHover_WM_LBUTTONDOWN, "__GUICtrl_SetOnHover_WM_LBUTTONDOWN")


далее в функции __MAIN_CALLBACK_ONHOVER_PROC находим условие начинающиеся с «If $aCursorInfo[2] = 1 And $aHOVER_CONTROLS_ARRAY[$i][3]» и перед этим условием (в том же «If») добавляем ещё одно:
Код:
$iLAST_PRIMARYDOWN_CTRLID = $iControl_Hovered And


Всё, теперь только осталось добавить сами WM-функции:
Код:
Func __GUICtrl_SetOnHover_WM_COMMAND($hWndGUI, $MsgID, $WParam, $LParam)
	$iLAST_PRIMARYDOWN_CTRLID = $LParam
EndFunc

Func __GUICtrl_SetOnHover_WM_LBUTTONDOWN($hWndGUI, $MsgID, $WParam, $LParam)
	$iLAST_PRIMARYDOWN_CTRLID = 0
EndFunc
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 702
Re: GUICtrlSetOnHover - Обработка событии при наведении

Да, но WM_LBUTTONDOWN будет работать только с окном, а если я нажму кнопку вне окна, или на другом элементе, или на заголовке окна? Здесь "малой кровью" не обойтись.

А почему ты не хочешь использовать _IsPressed()? Одним DllCall() больше, одним меньше, в данном случае это не имеет никакого значения, т.к. ты все равно используешь таймер. Дополнительная нагрузка будет практически незаметна.
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 156
Репутация
2 329
Re: GUICtrlSetOnHover - Обработка событии при наведении

Yashied [?]
почему ты не хочешь использовать _IsPressed()?
Попытался, не получилось приспособить, есть идеи? Кстати свой пост поправил немного, забыл там добавить переменную в начало.
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 156
Репутация
2 329
Re: GUICtrlSetOnHover - Обработка событии при наведении

Yashied [?]
WM_LBUTTONDOWN будет работать только с окном, а если я нажму кнопку вне окна, или на другом элементе, или на заголовке окна? Здесь "малой кровью" не обойтись.
Ты пробовал то что я написал? Мне пока не удалось найти ситуацию где бы это решение провалилось ;D. Ок, нашёл где это может не сработать - если при удерживании кнопки увести курсор за пределы окна и отпустить, то потом при удерживании вне окна и наведении над элементом, функция нажатия снова вызывается, но только для последнего нажатого элемента. Решение простое - добавить ещё одно условие: «And WinActive($hParent_Wnd[0])»...
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 702
Re: GUICtrlSetOnHover - Обработка событии при наведении

CreatoR сказал(а):
Ты пробовал то что я написал?
Выложи пожалуйста правленный UDF, я протестирую.

Кстати, я приспособил свой Icons.au3 для совместной работы с твойм GUICtrlSetOnHover_UDF.au3. Пока только на оф. форуме, но там я выложил прикольный пример, обязательно посмотри.

http://www.autoitscript.com/forum/index.php?showtopic=92675
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 702
Re: GUICtrlSetOnHover - Обработка событии при наведении

CreatoR сказал(а):
Ок, нашёл где это может не сработать - если при удерживании кнопки увести курсор за пределы окна и отпустить...
Не только за пределы окна, но и на любой другой элемент или заголовок.
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 156
Репутация
2 329
Re: GUICtrlSetOnHover - Обработка событии при наведении

Yashied [?]
Выложи пожалуйста правленный UDF
Ок, обновил.

там я выложил прикольный пример, обязательно посмотри
Клас, мне понравилось. Только вот ширина GUI большая, лучше ориентироваться по @DesktopWidth-10.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 702
Re: GUICtrlSetOnHover - Обработка событии при наведении

CreatoR сказал(а):
Клас, мне понравилось. Только вот ширина GUI большая, лучше ориентироваться по @DesktopWidth-10.
Да, об этом как-то не подумал.

OffTopic:
Когда на столе стоит 30", то сам понимаешь, о таких мелочах начинаешь забывать. :smile:
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 702
Re: GUICtrlSetOnHover - Обработка событии при наведении

CreatoR сказал(а):
Да, сейчас работает как нужно, спасибо. Более детально буду разбираться позже.

+1
 
Верх