Что нового

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

saavaage

Знающий
Сообщения
171
Репутация
17
CreatoR, вот:

http://autoit-script.ru/autoit_rv_ua/files/Administration/WORK_1(SmartXP).7z
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
saavaage [?]
периодически происходит зависание с выдачей такого сообщения
У меня не получается это воспроизвести :(
 

saavaage

Знающий
Сообщения
171
Репутация
17
CreatoR, Технология проверки такова:
1. запускаем,
2. перемещаемся мышкой по форме, вкл. все работающие на строку состояния контроллы (вкладка Итого ПК и вкладка Ошибки)
3. пробуем выйти через нажатие на правый верхний крестик
4. одна из 5 (в среднем) попытки приводит к краху

PS проверял не только на своем ПК
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Получилось :smile:
Вся проблема в _CleanDatas(), нужно добавить GUIDelete() и убрать паузы оттуда, я вообще не понмаю смысл в них.

Код:
Func _CleanDatas()
	GUIDelete($hMain_GUI)
	
	FileDelete(@WindowsDir&'\regperm.exe')
	FileDelete(@HomeDrive &'\My_IE_EasySec.reg')
	FileDelete(@MyDocumentsDir&'\my_localpolicy_Ip.ipsec')
	FileDelete(@HomeDrive & '\dx.txt')
	FileDelete(@WindowsDir&'\setenv.exe')
	FileDelete(@HomeDrive & '\reg.dat')
EndFunc


так вроде завершает работу без проблем.
 

saavaage

Знающий
Сообщения
171
Репутация
17
CreatoR, я пробовал вообще комментить эту функцию. Тоже сначало вроде все ок, однако потом тоже самое выскакивает. Только реже.

ХМ, сейчас попробовал сделать, что Вы предложили и вроде пока все ОК. Как протестю, отпишусь. Пока не копай глубже.
Спасибо, комрад!
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
saavaage [?]
я пробовал вообще комментить эту функцию
Этого мало, перед выходом желательно удалять все созданные GUI.
 

saavaage

Знающий
Сообщения
171
Репутация
17
CreatoR, это касается и дочерних окон? Разве они не удаляются при закрытии?
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
saavaage [?]
это касается и дочерних окон?
Нет, дочерние окна удаляются при удалений родительских.

Разве они не удаляются при закрытии?
При нажатий на кнопку закрытия? Нет, при закрытий посылается событие, а дальше это уже ответственность “пользователя” (т.е скриптера) удалить GUI. При выходе из скрипта (Exit) естественно GUI удаляются, но делается это одновременно с высвобождением ресурсов программы, отсюда и могут возникнуть проблемы с памятью (утечка памяти), т.ч лучше удалять то что можно самим. Кстати, не помешало бы вызывать и высвобождение ресурсов «GUICtrlOnHover»:

Код:
__GUICtrl_SOH_ReleaseResources()
Exit

ну или через
Код:
_GUICtrl_OnHoverRegister($iCtrlID, "")

для каждого элемента.
 

saavaage

Знающий
Сообщения
171
Репутация
17
CreatoR, если я правильно Вас понял, то необходимо:
1. удалять все дочерние окна при заждом их закрытии
2. высвобождать ресурсы GUICtrlOnHover для каждого элемента. Если можно, поясните, это необходимо делать когда? Перед закрытием или привязывать к контролам как и регистрацию?
Я думаю, что перед выходом из программы добавить
Код:
__GUICtrl_SOH_ReleaseResources()
Exit

. Правильно?
полученный кусок кода:

Код:
; функция закрытия через крест
Func CLOSEClicked()
		_GUICtrl_SOH_ReleaseResources()
                            _CleanDatas()
	Exit
EndFunc
.................................

; фукция вызова/закрытия дочерних окон
Func _MainGUI_Events()
	Switch @GUI_CtrlId
		Case $nExit_Button, $GUI_EVENT_CLOSE
                                          _GUICtrl_SOH_ReleaseResources()
			_CleanDatas()
			
            Exit
                           Case ...

	EndSwitch
EndFunc


3. Если я применяю регистрацию функции, например, так:
Код:
$Button_CreateNew = GUICtrlCreateButton('Меню "Создать"', 115, 400, 80, 33, $BS_MULTILINE)
_GUICtrl_OnHoverRegister(-1, '_Hover_Func', '_Leave_Hover_Func')
GUICtrlSetCursor(-1, 0)

Это правильно? или лучше делать так
Код:
$Button_CreateNew = GUICtrlCreateButton('Меню "Создать"', 115, 400, 80, 33, $BS_MULTILINE)
_GUICtrl_OnHoverRegister($Button_CreateNew, '_Hover_Func', '_Leave_Hover_Func')
GUICtrlSetCursor(-1, 0)



Добавлено:
Сообщение автоматически объединено:

Еще один вопрос:
что предпочтительнее?

Код:
_GUICtrl_SOH_ReleaseResources()
Exit

при выходе

или

Код:
_GUICtrl_OnHoverRegister($iCtrlID, "")

для каждого элемента.
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
saavaage [?]
Это правильно? или лучше делать так
В данном случае разницы нет, -1 проебразовывается в CtrlID.

что предпочтительнее?
Если вызывать один раз перед завершением скрипта, то конечно первое, хотя оно и не документировано.
 

saavaage

Знающий
Сообщения
171
Репутация
17
CreatoR, а на первую часть вопроса не ответите?

На всякий, дублирую:

если я правильно Вас понял, то необходимо:
1. удалять все дочерние окна при заждом их закрытии

2. высвобождать ресурсы GUICtrlOnHover для каждого элемента. Если можно, поясните, это необходимо делать когда? Перед закрытием или привязывать к контролам как и регистрацию?
Я думаю, что перед выходом из программы добавить
Код:
__GUICtrl_SOH_ReleaseResources()
Exit

. Правильно?
полученный кусок кода:

Код:
; функция закрытия через крест
Func CLOSEClicked()
        _GUICtrl_SOH_ReleaseResources()
                            _CleanDatas()
    Exit
EndFunc
.................................

; фукция вызова/закрытия дочерних окон
Func _MainGUI_Events()
	Switch @GUI_CtrlId
		Case $nExit_Button, $GUI_EVENT_CLOSE
			   __GUICtrl_SOH_ReleaseResources()
			   _CleanDatas()
            Exit
.........................................
	EndSwitch
EndFunc

Если несложно, посмотрите, плиз, этот архив. Вроде все сделал, но при открытии дочерних окон (Вкладка Папки: Создать и Prefetch, вкладка Безопасность: кнопка "Доступ к Дискам") происходит зависание утилиты и иногда опять вылетает при выходе:

http://autoit-script.ru/autoit_rv_ua/files/Administration/WORK_1(SmartXP).7z
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
saavaage [?]
перед выходом из программы добавить
Всё верно, я это и показал в примере.

происходит зависание утилиты и иногда опять вылетает при выходе
Я бы использовал дополнительную функцию для закрытия вместо Exit:

Код:
Func _Exit()
	GUIDelete($hMain_GUI)
	__GUICtrl_SOH_ReleaseResources()
    _CleanDatas()
	Exit
EndFunc


А также, поскольку тут очень много элементов которым нужно регистрировать наведение (Hovering), я бы поместил всё это дело в отдельную функцию, чтобы при вызове дочерних окон одним махом отменять регистрацию и позже снова её ставить.
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
[?]
я бы поместил всё это дело в отдельную функцию, чтобы при вызове дочерних окон одним махом отменять регистрацию и позже снова её ставить
Вот так (см. вложение).

Хотя зависания иногда проявляются, это видимо как то связано с утечкой памяти, как это исправить, трудно сказать, скрипт не маленький :smile:
 

saavaage

Знающий
Сообщения
171
Репутация
17
CreatoR, немного не понял эту конструкцию:
Код:
Func CLOSEClicked()
	_Exit()
EndFunc

Func _Exit()
	GUIDelete($hMain_GUI)
	__GUICtrl_SOH_ReleaseResources()
    _CleanDatas()
	Exit
EndFunc


Разве это не одно и тоже:
Код:
Func CLOSEClicked()
	GUIDelete($hMain_GUI)
	__GUICtrl_SOH_ReleaseResources()
    _CleanDatas()
	Exit
EndFunc
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
saavaage [?]
Разве это не одно и тоже
_Exit() используется и в других местах, можно конечно назначить её вместо «CLOSEClicked» в GUISetOnEvent.
 

saavaage

Знающий
Сообщения
171
Репутация
17
CreatoR, в конечном итоге выкрутился через:

AdlibRegister('_StatusBarText')
AdlibUnRegister('_StatusBarText')

Код:
Func _StatusBarText()
       Local $aCursor = GUIGetCursorInfo()
    If IsArray($aCursor) Then
        Switch $aCursor[4]
		; вкладка Итого ПК
				Case $Logo
					GUICtrlSetData($hStatus, 'Здесь можно перейти на страницу утилиты на форуме OsZone.')
				Case $nExit_Button
					GUICtrlSetData($hStatus, 'Выйти из программы')

	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                Case Else
			   GUICtrlSetData($hStatus, "Вывод пояснительной инфо по кнопкам")
		EndSwitch
	EndIf
EndFunc

Вроде работает без тормозов (если интересно, могу выложить)
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
saavaage [?]
в конечном итоге выкрутился через
Я нашёл проблему, GUICtrlOnHover.au3 использует Callback, как известно Callback-функция должна возвращать как можно быстрее, и видимо иногда время обработки занимает дольше обычного (положенного), отсюда и зависания.

Прикрепляю исправленный скрипт (где ещё с _GUICtrl_OnHoverRegister(-1...)), с библиотекой где вместо Callback используется AdlibRegister. Вроде работает без зависаний.
 

saavaage

Знающий
Сообщения
171
Репутация
17
CreatoR, спасибо. означает ли это, что скоро будет обновление функции? :smile:

Предварительное тестирование проблем не выявило. Скрипт работает стабильно, подсказки выводятся молниеносно, зависаний как самого скрипта, так и дочерних окон тоже не выявлено (был небольшой косячок с "Доступ к Дискам", но это мой косячок).
Еще раз спасибо. Если будут проблемы у тестеров, обязательно отпишусь.
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
saavaage [?]
означает ли это, что скоро будет обновление функции?
Да. Но следует помнить о недостатках такого подхода. Любая блокирующая функция или дополнительный цикл, приведут к тому, что функция события (наведения) не будет вызвана.
Поэтому при обновлений библиотеки я просто добавлю версию без Callback (GUICtrlOnHover_NoCallback.au3).
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Пример панельки со «скользящей рамкой» при наведении курсора над элементами:

Код:
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <Misc.au3>

#include "GUICtrlOnHover.au3"

Global $iToolbarBox_TimeOut = 500 ;ToolbarBox (hoverbox) timeout (in ms)
Global $iCtrl_Hover_Event = 0
Global $iCtrl_Pressed_Event = 0

$hForm = GUICreate("_ToolbarBox With SliderBox Demo", 500, 200) ;Create teh form

$Edit = GUICtrlCreateEdit("", 0, 40, 500, 160) ;Create an edit box
GUICtrlSetData(-1, "Edit1") ;Set the editbox data to: "Edit1"

$Line = GUICtrlCreateGraphic(5, 30, 490, 1, 0x08) ;Create the pretty line under all these Toolbar items

;Set the images and the events
$iLeft = 5

For $i = 1 To 12
	GUICtrlCreateIcon("Shell32.dll", -(Random(1, 239)), $iLeft, 5, 16, 16)
	_GUICtrl_OnHoverRegister(-1, "_ToolbarBox_HoverEvent", "_ToolbarBox_UnHoverEvent", "", "_ToolbarBox_PressedEvent", 1, 1)
	
	$iLeft += 25
Next

GUISetState() ;Show the form

$hToolbarBox = _ToolbarBox_Init($hForm) ;Init the toolbar functionality

While 1
	$nMsg = GUIGetMsg()
	
	Switch $nMsg
		Case $GUI_EVENT_CLOSE
			Exit
	EndSwitch
	
	If $iCtrl_Hover_Event <> 0 Then
		$i_CtrlID = $iCtrl_Hover_Event
		$iCtrl_Hover_Event = 0
		
		_ToolbarBox_Event($hForm, $i_CtrlID)
	EndIf
	
	If $iCtrl_Pressed_Event Then
		GUISetState(@SW_HIDE, $hToolbarBox)
		
		$i_CtrlID_Pressed = $iCtrl_Pressed_Event
		$iCtrl_Pressed_Event = 0
		
		MsgBox(64, "Title", "Event recieved from CtrlID: " & $i_CtrlID_Pressed, 0, $hForm)
	EndIf
WEnd

Func _ToolbarBox_Init($hWnd)
	$iToolbarBox_Timer = TimerInit()
	
	Local $h_ReturnBox = GUICreate("", 23, 23, 1 + 50, 1, 0x80000000, BitOR(0x00080000, 0x00000040), $hWnd)
	
	If Not FileExists(@TempDir & "\~Toolbar_Square.gif") Then
		Local $hFOpen = FileOpen(@TempDir & "\~Toolbar_Square.gif", 18)
		
		FileWrite($hFOpen, "0x47494638396117001700F72A00000000FFFFFF7B91B42B4F822D508" & _
				"22E51832F51835F7CA82D518345668F4768904B6C934E6D93527196A8B7CA4B6C92547396F5E8A1F4" & _
				"E49CF3DE96F1D78EEFCF86EDC77CEDC77DEBBF73EBBE73E9B568E8B569E7AC5EE4A354E7AB5EE29A4" & _
				"AE5A254DE8A38E09141E09242DB7E2BDD8331DC8331DE8A39DA7926DB7D2B00000000000000000000" & _
				"000000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
				"000000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
				"000000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
				"000000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
				"000000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
				"000000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
				"000000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
				"000000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
				"000000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
				"000000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
				"000000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
				"000000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
				"000000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
				"000000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
				"000000000000000000000000000000000000000000000000000000000000000000000000000000000" & _
				"000000000000000000000000000000000000000000000000021F9040100002A002C00000000170017" & _
				"000008A20055081C48B0A0C1810E201418C0B0A1C38703103C70A08281800818336ADC98510003150" & _
				"6221C1C39308201150444921C1981004A092B474A70496042CC83136852B8699002CD0A3C0B56A079" & _
				"2128410B3433181D8881A686A502373885AA422A4A0F5439D00441B503CD0F543FD014417504CD135" & _
				"443D02C41D5044D125453B83480822A8A93090EA0D8CBB7AF5FBE0714A870D0C00081C388132B2650" & _
				"60818380003B")
		
		FileClose($hFOpen)
	EndIf
	
	GUICtrlCreatePic(@TempDir & "\~Toolbar_Square.gif", 0, 0, 0, 0)
	GUISetState(@SW_HIDE, $h_ReturnBox)
	
	Return $h_ReturnBox
EndFunc

Func _ToolbarBox_Reset()
	AdlibUnRegister("_ToolbarBox_Reset")
	GUISetState(@SW_HIDE, $hToolbarBox)
EndFunc

Func _ToolbarBox_Event($hWnd_Parent, $iCtrlID, $sEvent_Function = "", $iJump = False)
	Local $aCInfo = GUIGetCursorInfo($hWnd_Parent)
	If $aCInfo[4] <> $iCtrlID Then Return
	
	Local $aCtrl_Pos = ControlGetPos($hWnd_Parent, "", $iCtrlID)
	
	Local $aWin_Pos = WinGetPos($hWnd_Parent)
	Local $aClient_Size = WinGetClientSize($hForm)
	
	Local $aSmall_Border = ($aWin_Pos[2] - $aClient_Size[0]) / 2
	Local $aBig_Border = $aWin_Pos[3] - $aClient_Size[1] - $aSmall_Border

	Local $iX_Coord = $aWin_Pos[0] + $aSmall_Border + $aCtrl_Pos[0] - 4
	Local $iY_Coord = $aWin_Pos[1] + $aBig_Border + 1
	
	If $iJump Then WinMove($hToolbarBox, "", $iX_Coord, $iY_Coord)

	If WinGetState($hToolbarBox) > 5 Then
		Local $aToolbarBox_Pos = WinGetPos($hToolbarBox)
		Local $iFade_Range = Abs($iX_Coord - $aToolbarBox_Pos[0])

		If $aToolbarBox_Pos[0] > $iX_Coord Then
			For $i = $aToolbarBox_Pos[0] To $iX_Coord + 20 Step -15
				WinMove($hToolbarBox, "", $i, $iY_Coord)
				Sleep(1)
			Next

			For $i = $iX_Coord + 20 To $iX_Coord + 8 Step -5
				WinMove($hToolbarBox, "", $i, $iY_Coord)
				;Sleep(1)
			Next

			For $i = $iX_Coord + 8 To $iX_Coord Step -1
				WinMove($hToolbarBox, "", $i, $iY_Coord)
				;Sleep(1)
			Next

			WinMove($hToolbarBox, "", $iX_Coord, $iY_Coord, $aToolbarBox_Pos[2], $aToolbarBox_Pos[3], 1)
		ElseIf $aToolbarBox_Pos[0] < $iX_Coord Then
			For $i = $aToolbarBox_Pos[0] To $iX_Coord - 20 Step 15
				WinMove($hToolbarBox, "", $i, $iY_Coord)
				Sleep(1)
			Next
			
			For $i = $iX_Coord - 20 To $iX_Coord - 8 Step 5
				WinMove($hToolbarBox, "", $i, $iY_Coord)
				;Sleep(1)
			Next

			For $i = $iX_Coord - 8 To $iX_Coord Step 1
				WinMove($hToolbarBox, "", $i, $iY_Coord)
				;Sleep(1)
			Next

			WinMove($hToolbarBox, "", $iX_Coord, $iY_Coord, $aToolbarBox_Pos[2], $aToolbarBox_Pos[3], 1)
		EndIf
		
		If $iJump Then WinMove($hToolbarBox, "", $iX_Coord, $iY_Coord)
	Else
		WinMove($hToolbarBox, "", $iX_Coord, $iY_Coord)
		GUISetState(@SW_SHOWNOACTIVATE, $hToolbarBox)
	EndIf
	
	If $sEvent_Function <> "" Then
		Local $aCInfo = GUIGetCursorInfo($hWnd_Parent)
		
		While $aCInfo[4] = $iCtrlID
			If GUIGetMsg() = $iCtrlID Then
				If _IsPressed(01) Then
					While _IsPressed(01)
						Sleep(10)
					WEnd
					
					Call($sEvent_Function, $iCtrlID)
					If @error Then Call($sEvent_Function)
					
					ExitLoop
				EndIf
			EndIf
			
			$aCInfo = GUIGetCursorInfo($hWnd_Parent)
		WEnd
	EndIf
	
	If $iJump Then GUISetState(@SW_HIDE, $hToolbarBox)
EndFunc

Func _ToolbarBox_PressedEvent($iCtrlID)
	$iCtrl_Pressed_Event = $iCtrlID
EndFunc

Func _ToolbarBox_HoverEvent($iCtrlID, $iHoverMode)
	$iCtrl_Hover_Event = $iCtrlID
EndFunc

Func _ToolbarBox_UnHoverEvent($iCtrlID, $iHoverMode)
	AdlibRegister("_ToolbarBox_Reset", $iToolbarBox_TimeOut)
EndFunc
 
Верх