Что нового

Замена GUIRegisterMsg

asdf8

Скриптер
Сообщения
564
Репутация
152
Попробовал сделать так :

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

$Form = GUICreate("Test", 262, 256, -1, -1)
$TreeView = GUICtrlCreateTreeView(4, 4, 253, 245)
$TV_1 = GUICtrlCreateTreeViewItem("Item 1", $TreeView)
$TV_1_1 = GUICtrlCreateTreeViewItem("Item 1.1", $TV_1)
$TV_1_2 = GUICtrlCreateTreeViewItem("Item 1.2", $TV_1)
$TV_2 = GUICtrlCreateTreeViewItem("Item 2", $TreeView)
$TV_2_1 = GUICtrlCreateTreeViewItem("Item 2.1", $TV_2)
$TV_2_2 = GUICtrlCreateTreeViewItem("Item 2.2", $TV_2)
GUISetState(@SW_SHOW)

$hCtrl = GUICtrlGetHandle($TreeView)
$iDllCallback = DllCallbackRegister('_Proc', "ptr", "hwnd;uint;long;ptr")
OnAutoItExitRegister('_Exit')
$hPrevProc = _WinAPI_SetWindowLong($hCtrl, $GWL_WNDPROC, DllCallbackGetPtr($iDllCallback))

While 1
	$nMsg = GUIGetMsg()
	Switch $nMsg
		Case $GUI_EVENT_CLOSE
			Exit
	EndSwitch
WEnd

Func _Proc($hWnd, $iMsg, $wParam, $lParam)
	If $iMsg = $WM_NOTIFY Then
		ConsoleWrite('--- WM_NOTIFY' & @CRLF)
	EndIf
	Return _WinAPI_CallWindowProc($hPrevProc, $hWnd, $iMsg, $wParam, $lParam)
EndFunc

Func _Exit()
	If HWnd($hCtrl) Then _WinAPI_SetWindowLong($hCtrl, $GWL_WNDPROC, DllCallbackGetPtr($hPrevProc))
	DllCallbackFree($iDllCallback)
EndFunc


но сообщение (в данном случае WM_NOTIFY) приходит только один раз и , соответственно, пользоваться этим невозможно.
 
Автор
A

asdf8

Скриптер
Сообщения
564
Репутация
152
CreatoR [?]

Попробовал, используя эту UDF, в справочном примере к функции _GUICtrlTreeView_Create заменить :

Код:
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")


на :
Код:
_GUICtrlMsg_Register($hTreeView, $WM_NOTIFY, "WM_NOTIFY")


ничего не работает.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,487
asdf8 [?]
ничего не работает
Насколько я понял, это для встроенных элементов, для внешних нужно делать свой обработчик.
 
Автор
A

asdf8

Скриптер
Сообщения
564
Репутация
152
CreatoR [?]
Насколько я понял, это для встроенных элементов, для внешних нужно делать свой обработчик.

Все разрешилось довольно просто - в моем примере из первого поста обработчик нужно цеплять к родительскому окну, т.е. заменить :
Код:
$hCtrl = GUICtrlGetHandle($TreeView)

на :
Код:
$hCtrl = $Form
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
А чем не устраивает GUIRegisterMsg()?
 
Автор
A

asdf8

Скриптер
Сообщения
564
Репутация
152
Yashied [?]
А чем не устраивает GUIRegisterMsg()?

Тем, что регистрация сообщения этой функцией уничтожает предыдущую регистрацию этого же сообщения, и, при этом, я не имею возможности из своей UDF узнать о регистрации такого же сообщения в основном коде программы или в другом подключенном UDF.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Да, это неудобно. Но это актуально, если вы пишите UDF (для других). Но хук процедуры обработки окна в AutoIt может убить все достоинства остального кода. Если уж и делать это, то в отдельной DLL или на машинном коде.
 
Автор
A

asdf8

Скриптер
Сообщения
564
Репутация
152
Yashied [?]
Да, это неудобно. Но это актуально, если вы пишите UDF (для других).
Не вижу никакой разницы для кого UDF, для себя или для других. Если код достаточно сложен, то через месяц-другой вряд ли захочется в нем снова разбираться.
С остальным согласен.

PS: судя по всему, разработчики AutoIt легко могли бы сделать так, чтобы GUIRegisterMsg мог регистрировать одно сообщение несколько раз (с разными id), но это, похоже, их не волнует.
 

CreatoR

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

asdf8

Скриптер
Сообщения
564
Репутация
152
CreatoR [?]
Судя по тому, что постам уже 3 года, как то слабо это волнует.
Да и идея с возвращением предыдущей зарегистрированной функции не кажется лично мне удачной, а если функций было зарегистрировано больше 2-х и какая то из функций была разрегистрирована по ходу выполнения скрипта.
Пример с _WinAPI_CallWindowProc показывает, что несколько зарегистрированных функций могли бы обрабатываться последовательно, пока одна из зарегистрированный функций не перехватила сообщение.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,487
asdf8 [?]
идея с возвращением предыдущей зарегистрированной функции не кажется лично мне удачной
Но там валик упоминает о надобности сделать это по аналоги с функцией AdlibRegister, т.ч в таком виде оно будет отвечать требованиям.
 
Автор
A

asdf8

Скриптер
Сообщения
564
Репутация
152
CreatoR [?]
Но там валик упоминает о надобности сделать это по аналоги с функцией AdlibRegister, т.ч в таком виде оно будет отвечать требованиям.

Какой хитрый валик :laugh:.
Тогда он уже все сделал по данному тикету - AdlibRegister тоже ничего не возвращает, а посто заменяет предыдущий таймер.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,487
asdf8 [?]
AdlibRegister тоже ничего не возвращает, а посто заменяет предыдущий таймер
Он не заменяет таймер, там можно прописать дополнительную функцию таймера. Если также будет работать GUIRegisterMsg, то большего и не нужно.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Самое грамотное решение для сохранения совместимости с текущими скриптами. Приоритет будет отдаваться последней зарегистрированной функции, т.е. если функция возвращает значение отличное от $GUI_RUNDEFMSG, то все нижестоящие функции пропускаются.
 
Верх