Что нового

Вызывать функции с параметрами

Атос

Новичок
Сообщения
85
Репутация
0
Подскажите функцию, которая может вызывать другие функции с параметрами.

Я так понял, что GUICtrlSetOnEvent не может вызывать функции с параметрами, правильно?

Вот пример.
Код:
Opt("GUIOnEventMode", 1)
GUICreate("111")
Local $aaa = GUICtrlCreateButton("Start", 55, 15,  40, 22, 0x0100)
GUISetState()
GUICtrlSetOnEvent($aaa, "_a1('C:\Enigma--Following.The.Sun.mp3')")
GUISetOnEvent(-3, "_CLOSE")

While 1
Sleep(1000)
WEnd

Func _a1($f)
ShellExecute($f)
EndFunc

Func _CLOSE() 
Exit 
EndFunc


Т.е., мне надо с индификатора кнопки вызвать функцию с нужными мне параметрами.
 

СН3СН2ОН

Знающий
Сообщения
78
Репутация
12
Код:
Opt("GUIOnEventMode", 1)
GUICreate("111")
Local $aaa = GUICtrlCreateButton("Start", 55, 15,  40, 22, 0x0100)
GUISetState()
GUICtrlSetOnEvent($aaa, "_a1")
GUISetOnEvent(-3, "_CLOSE")


Global $f = 'C:\Enigma--Following.The.Sun.mp3'


While 1
Sleep(1000)
WEnd

Func _a1()
	ShellExecute($f)
EndFunc

Func _CLOSE()
Exit
EndFunc

Код не запускал.
Вы хотите сделать запуск с кнопки? функции? с параметром?
Тогда как-то так. То есть параметр $f меняется, допустим что-то ввели.
А если параметр статичный... то то же так можно.
 
Автор
А

Атос

Новичок
Сообщения
85
Репутация
0
СН3СН2ОН, Ваш метод не подходит.

Дело в том, что параметры динамические и абсолютно неизвестные.

Т.е., я не могу знать, какие объявлять глобальные переменные или константы.
 
A

Alofa

Гость
Восстановленно
Атос сказал(а):
... мне надо с индификатора кнопки вызвать функцию с нужными мне параметрами.
Вы заблуждаетесь - вам этого не нужно. Поясню.
И так, что мы видим в данной строке (кроме нарушения синтаксиса)?
Код:
GUICtrlSetOnEvent($aaa, "_a1('C:\Enigma--Following.The.Sun.mp3')")

- желание передать в функцию 'C:\Enigma--Following.The.Sun.mp3'. А это что? Правильно - путь, заведомо известный или который можно вычислить/узнать уже внутри самой функции "_a1()".
 
A

Alofa

Гость
Как скрипт узнает о 'C:\Enigma--Following.The.Sun.mp3'?
 
Автор
А

Атос

Новичок
Сообщения
85
Репутация
0
Это для примера.

Вы можете вставить любой другой путь.
Хоть текстовый, хоть бинарный.

Мне главное вызвать функцию с нужными мне параметрами.
Вот другой пример.

Код:
Opt("GUIOnEventMode", 1)
GUICreate("111")
Local $aaa = GUICtrlCreateButton("Start", 55, 15,  40, 22, 0x0100)
GUISetState()
GUICtrlSetOnEvent($aaa, "_a1('Bavaria')")
GUISetOnEvent(-3, "_CLOSE")

While 1
Sleep(1000)
WEnd

Func _a1($a)
MsgBox(0, "title", $a)
EndFunc

Func _CLOSE()
Exit
EndFunc
 
A

Alofa

Гость
Атос сказал(а):
Это для примера.
Я в курсе.

Атос сказал(а):
... параметры динамические и абсолютно неизвестные.
Рано или поздно вы их как-то узнаете? Как? Покажите пример в коде.


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

Атос сказал(а):
... Мне главное вызвать функцию с нужными мне параметрами...
Вы мыслите неправильно - не надо на этом зацикливаться.
Вам нужно чтобы функция сработала правильно.
 
Автор
А

Атос

Новичок
Сообщения
85
Репутация
0
Код практически ещё пустой.
Я его только начал разрабатывать.
Всё встало на этом моменте.
Если я найду решение, или мне помогут, то я его буду продолжать разрабатывать.
 
A

Alofa

Гость
Вот маленький пример, изучите логику его работы:
Код:
Opt("GUIOnEventMode", 1)
GUICreate("111")
Local $iAaa_1 = GUICtrlCreateButton("Вариант 1", 55, 40)
Local $iAaa_2 = GUICtrlCreateButton("Вариант 2", 155, 40)
Local $iDate = GUICtrlCreateDate("1953/04/25", 10, 80, 185, 20)
GUICtrlSetOnEvent($iAaa_1, "_a1")
GUICtrlSetOnEvent($iAaa_2, "_a2")
GUISetOnEvent(-3, "_CLOSE")
GUISetState()

While 1
	Sleep(1000)
WEnd

Func _a1()
	; $sFile - это то что нам нужно для выполнения функции (для примера)
	Local $sFile = FileOpenDialog('Так узнаем путь до файла:', @ScriptDir, '(*.mp3)')
	If @error Then Return
	ShellExecute($sFile)
EndFunc   ;==>_a1

Func _a2()
	MsgBox(262144, Default, GUICtrlRead($iDate))
EndFunc   ;==>_a1

Func _CLOSE()
	Exit
EndFunc   ;==>_CLOSE
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
Атос
Чем вас не устраивает вариант ниже?
Код:
#include <GUIConstantsEx.au3>

Local $hWnd = GUICreate("")
Local $iButton = GUICtrlCreateButton("play", 310, 370, 85, 25)

GUISetState(@SW_SHOW)

While 1
   Switch GUIGetMsg()
	  Case $GUI_EVENT_CLOSE
		 ExitLoop
	  Case $iButton
		 _a1('C:\Enigma--Following.The.Sun.mp3')
   EndSwitch
WEnd

Func _a1($f)
   ShellExecute($f)
EndFunc
 
Автор
А

Атос

Новичок
Сообщения
85
Репутация
0
Garrett, вполне устраивает. Как раз, такое ищу. Спасибо.
 
Автор
А

Атос

Новичок
Сообщения
85
Репутация
0
У меня не получается приспособить это решение к своей задаче.

Попробую сформулировать задачу более конкретно.
У меня есть цикл For To Next. StopValue - у меня будет двумерным массивом (Вернее, количеством элементов этого массива.).
Внутри этого цикла есть идентификатор кнопки.
С каждым новым циклом он меняется.
Будет вызываться одна и та же функция, но в зависимости от этого идентификатора, параметры будут меняться.
Соответственно, я не могу точно получить событие через Switch GUIGetMsg() EndSwitch.
В этом вся трудность.
Если бы, хотя-бы GUICtrlSetOnEvent($p, "_a1('Bavaria')") работала, то вся проблема бы ушла.
Если использовать GUICtrlRead($p) вне цикла, то я буду всегда получать последний элемент,
а мне нужен конкретный, в зависимости от номера цикла.
Получается замкнутый круг.
Вызов вне цикла - результат последний цикл.
Вызов внутри цикла - есть все динамические переменные, но невозможно вызвать функцию с конкретными параметрами.

Код:
Opt("GUIOnEventMode", 1)
GUICreate("111")
$p = 0
For $i = 0 To 7
$p = $p + $i
$p = GUICtrlCreateButton('Start', 15, 20, 160, 22, 0x0100)
GUICtrlSetOnEvent($p, "_a1('Bavaria')")
; GUICtrlSetOnEvent($p, "_a1")
Next
GUISetState()
GUISetOnEvent(-3, "_CLOSE")

While 1
Sleep(1000)
WEnd

; Func _a1()
Func _a1($a)
; MsgBox(0, "title", '1111')
MsgBox(0, "title", $a)
EndFunc

Func _CLOSE() 
Exit 
EndFunc
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Атос
Вам нужно какое нибудь хранилище, в котором будет хранится 1) ID кнопки и 2) Параметр (Бавария), который к этой кнопке привязан.
К сожалению нельзя прямо в кнопку записать свои параметры, хотя такая возможность была бы чертовски полезной. Разве что можно записать текст, но вряд ли будет красиво выглядеть кнопки, с текстом Start (Bavaria), хотя есть это вам не мешает, то можно и так сделать, если нет - читайте дальше.

Хранилища в autoit - можно пересчитать по пальцам старого фрезеровщика. Самое простое - это двумерный массив. Вы бы могли ID кнопки записывать в ячейку [1][0], а параметр в [1][1] для первой кнопки, и [2][0] [2][1] для второй, и так далее. Заметьте, что здесь я нумерую ячейки по порядку, от 1 до N без разрыва с шагом 1 - ведь это всего лишь хранилище, нам же не нужны там пустые ячейки да ;)
Вроде все хорошо и славно получается до тех пор, пока не нужно извлекать данные из него. Т.к найти в таком массиве что то - можно лишь полностью перебрав все элементы в нем, если он мелкий - то это не проблема. Но если у вас будет 100 кнопок, то уже стоит поискать что то другое.

Что то другое - это ассоциативные массивы или хэш массивы, которых в autoit нет.
Решение есть - можно использовать словарь - scripting.dictionary - в котором вы можете хранить в качестве ключей ID кнопок, а в качества параметра - вашу баварию. Это уже продвинутый вариант, примеры можно найти на форуме.

На все создаваемые кнопки навешивайте единственный обработчик, в вашем случае - GUICtrlSetOnEvent(ID кнопки, "_a1"). При нажатии кнопки, будет вызвана a1 без параметров, а что за кнопку, точнее ее ID вы сможете узнать через макрос @GUI_CtrlId и зная его, ищите в хранилище параметр, который к ней привязан.
 
Автор
А

Атос

Новичок
Сообщения
85
Репутация
0
inververs сказал(а):
Решение есть - можно использовать словарь - scripting.dictionary - в котором вы можете хранить в качестве ключей ID кнопок, а в качества параметра - вашу баварию.

inververs, спасибо. Попытаюсь реализовать это на практике.
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
inververs предлагает отличный вариант. Огромный плюс scripting.dictionary это динамическое расширение, ну и вызов по имени.
к слову, я сейчас работаю над программой, в которой динамически создаю элементы и присваиваю им функции, стили и так далее. вот как раз использую scripting.dictionary. id элементов идет как имя, а значение это массив, в котором храню все параметры элемента и меняю когда нужно.
Правда, обработка событий идет не через event, я использую wm_command для кнопок(радио, чек) для статик-элементов регистрируется функция wm_setcursor. при этом одна глобальная переменная, которую обновляют эти функции - присваивают ей id элемента, на который кликнул пользователь. А уже в основном цикле while...wend я обрабатываю этот id, вызываю из объекта его информацию и так далее, если функции простые, то можно обработать их прямо в wm_command и wm_setcursor
надеюсь, понятно написал :smile:
 
Автор
А

Атос

Новичок
Сообщения
85
Репутация
0
joiner, спасибо. У меня похожая задача.
Я считываю с ini-файла ключ-значение в двумерный массив.
Но как со словарями работать не совсем понятно.

Код:
Local $aSect = IniReadSection(@ScriptDir & '\Settings.ini', 'My')
GUICreate(111)
Local $h = 0, $p = 0, $z = '', $v = ''
For $i = 1 To $aSect[0][0]
$oDict = ObjCreate('Scripting.Dictionary')
$oDict.CompareMode = 1

$y = $oDict.Add($aSect[$i][0], $aSect[$i][1])
; $key = $oDict.Key($v) = $aSect[$i][0]
; $item = $oDict.Item($v) = $aSect[$i][1]
$p = GUICtrlCreateButton($aSect[$i][0], 15, 20, 160, 22, 0x0100)
$oDict.Key($v) = $aSect[$i][0]
$oDict.Item($v) = $aSect[$i][1]
; $ic = $oDict.Count()
$Arr = $oDict.Items()
; MsgBox(0, '111', $key)
; MsgBox(0, '111', $ic)
Next
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
Код:
#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
#include <WinApi.au3>

$oDict = ObjCreate('Scripting.Dictionary')
$oDict.CompareMode = 1
Global $nID
GUICreate(111)
Local $aSect = IniReadSection('путь', 'секция')
If @error Then Exit
Local $h = 0, $p = 0
For $i = 1 To $aSect[0][0]
	$p = GUICtrlCreateButton($aSect[$i][0], 15, $h, 160, 22, 0x0100)
	$oDict.Add($p, $aSect[$i][1])
	$h += 25
Next
GUISetState()
GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")
Local $gtd
While 1
	If $nID Then
		If $oDict.Exists($nID) Then
			$gtd = $oDict.Item($nID)
			MsgBox(64, 'Элемент ' & $nID, $gtd)
		EndIf
		$nID = 0
	EndIf
	Switch GUIGetMsg()
		Case -3
			Exit
	EndSwitch
WEnd

Func WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
	$nID = _WinAPI_LoWord($wParam)
	Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_COMMAND
 
Автор
А

Атос

Новичок
Сообщения
85
Репутация
0
joiner, гениально. Благодаря Вам, я закончу свой скрипт. Спасибо.
 
Верх