Что нового

Рекурсия в GUI интерфейсе

F9

Новичок
Сообщения
71
Репутация
2
Доброго времени суток.
Помогите разобраться с рекурсивным вызовом функции самой из себя:

Есть функция, которая цепляется к БД, заодно проверяя корректность подключения, чтобы в случае чего всегда можно было исправить данные, путем ввода в окно интерфейса корректных данных:

Код:
_mySQL_Connect(10.32.10.355,"root","")
;данные заведомо неверные, т.к. дебажим ошибки


Func _mySQL_Connect($server, $user, $pass)

Dim $sDatabase   = "pharm_zakaz"      ; База Данных к которой будем подключаемся

;проверка на ODBC драйвер, с которым гарантированно работает программа
Local $obdc_drv = "MySQL ODBC 3.51 Driver"
Local $key = "HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI\ODBC Drivers", $val = RegRead($key, $obdc_drv)
	If @error or $val = "" Then
			MsgBox(32,"Внимание","Вероятно не установлен"& @CR & $obdc_drv)
			Exit
	EndIf

Global $MySQLConn = ObjCreate("ADODB.Connection")
$MySQLConn.Open("DRIVER={MySQL ODBC 3.51 Driver};SERVER=" & $server & ";DATABASE=" & $sDatabase & ";UID=" & $user & ";PWD=" & $pass & ";PORT=3306" & "CHARSET=cp1251;")
;проверка на корректность настроек соединения.
	If not @error Then
		MsgBox("","","good")

	Else

		$reconnect_sql_gui = GUICreate("Не могу подключиться к mySQL", 300, 150, @DesktopWidth / 2 - 160, @DesktopHeight / 2 - 45, -1, $WS_EX_ACCEPTFILES)
		Global $reconnec_sql_server = GUICtrlCreateInput("", 100, 10, 160, 20)
		Global $reconnec_sql_user = GUICtrlCreateInput("", 100, 40, 160, 20)
		Global $reconnec_sql_pass = GUICtrlCreateInput("", 100, 70, 160, 20)
		$reconnec_sql_ok = GUICtrlCreateButton("OK",70,100,70,25)
		$reconnec_sql_cancel = GUICtrlCreateButton("Cancel",200,100,70,25)
		GUICtrlCreateLabel("mySQL Server",10,10)
		GUICtrlCreateLabel("mySQL User",10,40)
		GUICtrlCreateLabel("mySQL Password",10,70)
		GUISetState(@SW_SHOW)
			Do
			$msg = GUIGetMsg ()
				Select
					case $msg = $reconnec_sql_ok
					$server = GUICtrlRead($reconnec_sql_server)
					$user = GUICtrlRead($reconnec_sql_user)
					$pass = GUICtrlRead($reconnec_sql_pass)
					GUIDelete($reconnect_sql_gui)
					_mySQL_Connect($server, $user, $pass)

				case $msg = $reconnec_sql_cancel
					Exit
				EndSelect

			Until $msg = $GUI_EVENT_CLOSE
		Exit

	EndIf

EndFunc


;после коннекта к базе, переходим к прочим отрисовкам интерфейса, извлечению данных из ini и т.п.
GUISetState(@SW_SHOW)
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
.....


Вопрос в следующем:
если исходные данные верны, то мы сразу попадаем на точку
Код:
MsgBox("","","good")
и программа работает в стандартном порядке.
Если же исходные данные не верны, то как положенно вводим корректные, опять попадаем в точку
Код:
MsgBox("","","good")
но на этом все заканчивается. Программа как бы выполняется, но ничего не происходит.

Ощущение, что функция должна что-то вернуть, но что?
Очень не хватает аналога "gotо" :scratch:
PS
Основной старт программы лежит не в теле функции, а сплошным текстом.
 

Medic84

Омега
Команда форума
Администратор
Сообщения
1,590
Репутация
341
Говорите про рекурсию, а названия функций разные.

Я бы так сделал, но насчет работоспособности не знаю, Вы дали лишь кусок программы:
Код:
Global $MySQLConn = Null

$idConnect = _mySQL_Connect("10.32.10.355","root","")

GUISetState(@SW_SHOW)
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
 
Func _mySQL_Connect($server, $user, $pass)
	Dim $sDatabase   = "pharm_zakaz"

	Local $obdc_drv = "MySQL ODBC 3.51 Driver"
	Local $key = "HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI\ODBC Drivers", $val = RegRead($key, $obdc_drv)
	
	If @error or $val = "" Then
			MsgBox(32,"Внимание","Вероятно не установлен"& @CR & $obdc_drv)
			Exit
	EndIf

	$MySQLConn = ObjCreate("ADODB.Connection")
	$MySQLConn.Open("DRIVER={MySQL ODBC 3.51 Driver};SERVER=" & $server & ";DATABASE=" & $sDatabase & ";UID=" & $user & ";PWD=" & $pass & ";PORT=3306" & "CHARSET=cp1251;")
	
	If @error Then
		$reconnect_sql_gui = GUICreate("Не могу подключиться к mySQL", 300, 150, @DesktopWidth / 2 - 160, @DesktopHeight / 2 - 45, -1, $WS_EX_ACCEPTFILES)
		Global $reconnec_sql_server = GUICtrlCreateInput("", 100, 10, 160, 20)
		Global $reconnec_sql_user = GUICtrlCreateInput("", 100, 40, 160, 20)
		Global $reconnec_sql_pass = GUICtrlCreateInput("", 100, 70, 160, 20)
		$reconnec_sql_ok = GUICtrlCreateButton("OK",70,100,70,25)
		$reconnec_sql_cancel = GUICtrlCreateButton("Cancel",200,100,70,25)
		GUICtrlCreateLabel("mySQL Server",10,10)
		GUICtrlCreateLabel("mySQL User",10,40)
		GUICtrlCreateLabel("mySQL Password",10,70)
		GUISetState(@SW_SHOW)
		While 1
			Switch GUIGetMsg()
				Case $reconnec_sql_ok
					$server = GUICtrlRead($reconnec_sql_server)
					$user = GUICtrlRead($reconnec_sql_user)
					$pass = GUICtrlRead($reconnec_sql_pass)
					GUIDelete($reconnect_sql_gui)
					_mySQL_Connect($server, $user, $pass)
				Case $reconnec_sql_cancel
					Exit
				Case $GUI_EVENT_CLOSE
					Exit
			EndSwitch
		WEnd
		Return 0
	EndIf
	
	Return 1
EndFunc
 

InnI

AutoIT Гуру
Сообщения
4,922
Репутация
1,432
А я бы сделал без рекурсии. В самой функции заменить MsgBox и, естественно, убрать рекурсивный вызов
Код:
If not @error Then
        ; MsgBox("","","good")
        Return 1
    Else
...
                Select
                    case $msg = $reconnec_sql_ok
                    $g_server = GUICtrlRead($reconnec_sql_server)
                    $g_user = GUICtrlRead($reconnec_sql_user)
                    $g_pass = GUICtrlRead($reconnec_sql_pass)
                    GUIDelete($reconnect_sql_gui)
                    ; _SQL_Connect($server, $user, $pass)
...
А вызывать в основном скрипте в цикле
Код:
Global $g_server = "10.32.10.355", $g_user = "root", $g_pass = ""
Do
Until _mySQL_Connect($g_server, $g_user, $g_pass)
Цикл можно и со счётчиком сделать. Ну и переменные нужны глобальные.
 
Автор
F9

F9

Новичок
Сообщения
71
Репутация
2
Medic84 сказал(а):
Говорите про рекурсию, а названия функций разные.
Пардон, это всего лишь опечатка при копи-пасте на форум


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

Medic84 сказал(а):
Говорите про рекурсию, а названия функций разные.

Я бы так сделал, но насчет работоспособности не знаю, Вы дали лишь кусок программы:
Код:
Global $MySQLConn = Null

$idConnect = _mySQL_Connect("10.32.10.355","root","")

GUISetState(@SW_SHOW)
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
 
Func _mySQL_Connect($server, $user, $pass)
	Dim $sDatabase   = "pharm_zakaz"

	Local $obdc_drv = "MySQL ODBC 3.51 Driver"
	Local $key = "HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI\ODBC Drivers", $val = RegRead($key, $obdc_drv)
	
	If @error or $val = "" Then
			MsgBox(32,"Внимание","Вероятно не установлен"& @CR & $obdc_drv)
			Exit
	EndIf

	$MySQLConn = ObjCreate("ADODB.Connection")
	$MySQLConn.Open("DRIVER={MySQL ODBC 3.51 Driver};SERVER=" & $server & ";DATABASE=" & $sDatabase & ";UID=" & $user & ";PWD=" & $pass & ";PORT=3306" & "CHARSET=cp1251;")
	
	If @error Then
		$reconnect_sql_gui = GUICreate("Не могу подключиться к mySQL", 300, 150, @DesktopWidth / 2 - 160, @DesktopHeight / 2 - 45, -1, $WS_EX_ACCEPTFILES)
		Global $reconnec_sql_server = GUICtrlCreateInput("", 100, 10, 160, 20)
		Global $reconnec_sql_user = GUICtrlCreateInput("", 100, 40, 160, 20)
		Global $reconnec_sql_pass = GUICtrlCreateInput("", 100, 70, 160, 20)
		$reconnec_sql_ok = GUICtrlCreateButton("OK",70,100,70,25)
		$reconnec_sql_cancel = GUICtrlCreateButton("Cancel",200,100,70,25)
		GUICtrlCreateLabel("mySQL Server",10,10)
		GUICtrlCreateLabel("mySQL User",10,40)
		GUICtrlCreateLabel("mySQL Password",10,70)
		GUISetState(@SW_SHOW)
		While 1
			Switch GUIGetMsg()
				Case $msg = $reconnec_sql_ok
					$server = GUICtrlRead($reconnec_sql_server)
					$user = GUICtrlRead($reconnec_sql_user)
					$pass = GUICtrlRead($reconnec_sql_pass)
					GUIDelete($reconnect_sql_gui)
					_mySQL_Connect($server, $user, $pass)
				Case $reconnec_sql_cancel
					Exit
				Case $GUI_EVENT_CLOSE
					Exit
			EndSwitch
		WEnd
		Return 0
	EndIf
	
	Return 1
EndFunc

Хороший пример завесить комп
Код:
Recursion level has been exceeded - AutoIt will quit to prevent stack overflow.:
 

InnI

AutoIT Гуру
Сообщения
4,922
Репутация
1,432
F9
Хороший пример завесить комп
Вас честно предупредили о работоспособности.

Не страдайте... рекурсией - сделайте цикл. Хоть внутри функции, хоть снаружи.
Или вам чисто в академических целях - потренироваться?
 
Автор
F9

F9

Новичок
Сообщения
71
Репутация
2
InnI сказал(а):
F9
Хороший пример завесить комп
Вас честно предупредили о работоспособности.

Не страдайте... рекурсией - сделайте цикл. Хоть внутри функции, хоть снаружи.
Или вам чисто в академических целях - потренироваться?
А счетчиком цикла что использовать можно?
 

InnI

AutoIT Гуру
Сообщения
4,922
Репутация
1,432
F9
А счетчиком цикла что использовать можно?
Количество вызовов. Если, скажем, за 5 раз правильно не ввели... значит реальные проблемы... либо с базой, либо с пользователем.
 
Автор
F9

F9

Новичок
Сообщения
71
Репутация
2
InnI сказал(а):
F9
А счетчиком цикла что использовать можно?
Количество вызовов. Если, скажем, за 5 раз правильно не ввели... значит реальные проблемы... либо с базой, либо с пользователем.
Мне кажется в теории пользователю неважно - с чем проблемы, заданы невеорные параметры: предлагаем ввести верные пока введенные денные не окажутся верными или пока не нажмем "отмена".
Как мне кажется для такой ситуации рекурсивный вызов функции с передаваемыми параметрами - идеальный вариант.

Логика процесса такова:

Объявление переменных, создание формы GUI и т.п.
Соединяемся с базой.
Если ок - то переходим к
Код:
GUISetState(@SW_SHOW, $MainForm) 
.....
While 1
    $msg = GUIGetMsg(1)
Case $msg[0] = ...
Case $msg[0] = ...
...
WEnd

Если не ОК, то проверяем OBDC драйвер.
Если драйвер ОК, то проверяем коннектор к базе.
Если ошибка - предлагаем ввести корректные данные (основной интерфейс еще не отображен, т.к. в нем имеются элементы, источником данных который служат запросы) и запускаем процедуру коннекта еще раз, а затем еще раз и .т.п.

Загвоздка только в корректном выходе из функции, когда все условия выполнены.
Получается, что если все условия соединения выполнены и корректны изначально, при выходе из функции - все работает.
Если изначальные параметры неверны, то после изменений параметров соединения с mySQL - выходим из функции и ...висим. Ничего не происходит. :blink:

К сожалению весь код не могу предоставить - около 2000 строк, и обязательно наличие базы, определенных файлов и путей, а также расшаренных путей в сети.
 

InnI

AutoIT Гуру
Сообщения
4,922
Репутация
1,432
F9
после изменений параметров соединения с mySQL - выходим из функции и ...висим
После выполнения функции вследствие её рекурсивного вызова, вы возвращаетесь в точку вызова, т.е. в цикл While. Поэтому вам нужна проверка на успешность подключения и, соответственно, прерывание цикла
Код:
...
GUIDelete($reconnect_sql_gui)
_mySQL_Connect($server, $user, $pass)
If $IsConnectedOk Then ExitLoop
...
В вашем варианте можно заменить MsgBox, только переменная должна быть глобальной
Код:
If not @error Then
        ; MsgBox("","","good")
        $IsConnectedOk = True
    Else
 
Автор
F9

F9

Новичок
Сообщения
71
Репутация
2
Спасибо большое.
Элементарно, а я не допёр ((( :whistle:
 
Верх