Что нового

[Массивы] Наполнение "GUICtrlCreateCombo" данными из двухмерного массива

panda_911

Только вверх, только вперед!
Сообщения
52
Репутация
8
Здравствуйте!
Снова необходима ваша помощь :smile:
Есть двухмерный массив:
i_petrov pass1
v_ivanov pass2
s_sidorov pass3
необходимо следующее.
При выборе значения из меню "комбо" вернуть/получить две переменные.
Например если выбрали s_sidorov, то получили
Код:
$1 = s_sidorov
$2 = pass3

Возможно не совсем корректно сформулировал задачу, но как смог.
Просто необходимо чтоб пользователь выбрав из списка один пункт, получил в двух других значения из одного массива одной строки но разных колонок. Размер массива наверное будет более многомерным так как возможно придется добавлять еще параметры. Но сейчас хотелось бы попробовать реализовать с двухмерным.
Как я себе это представляю нужно присвоить индексы и с ними играться, но не знаю как это сделать :(

*в моей прошлой теме мне помогли реализовать похожее с кнопками но перестроить ее на Combo у меня не вышло
http://autoit-script.ru/index.php/topic,7107.0.html
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
Логичнее будет выбирать account
Код:
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>

Dim $aAccount[3][2] = _
	[['i_petrov', 'pass1'], _
	 ['v_ivanov', 'pass2'], _
	 ['s_sidorov','pass3']]


$Form1 = GUICreate("Form1", 161, 83, 443, 209)
$Input1 = GUICtrlCreateInput("", 6, 30, 145, 21)
$Input2 = GUICtrlCreateInput("", 6, 54, 145, 21)
$Combo1 = GUICtrlCreateCombo("--//--", 6, 6, 145, 25)
GUICtrlSetData(-1, "Account1|Account2|Account3")
GUISetState(@SW_SHOW)

While 1
	$nMsg = GUIGetMsg()
	Switch $nMsg
		Case $GUI_EVENT_CLOSE
			Exit
		Case $Combo1
			$sCombo1 = GUICtrlRead($Combo1)
			Switch $sCombo1
			Case 'Account1'
				GUICtrlSetData($Input1, $aAccount[0][0])
				GUICtrlSetData($Input2, $aAccount[0][1])
			Case 'Account2'
				GUICtrlSetData($Input1, $aAccount[1][0])
				GUICtrlSetData($Input2, $aAccount[1][1])				
			Case 'Account3'
				GUICtrlSetData($Input1, $aAccount[2][0])
				GUICtrlSetData($Input2, $aAccount[2][1])				
			EndSwitch
	EndSwitch
WEnd


Автозаполнение Combo на всякий случай :smile:
Это, если вы всё же решите выбирать по имени.
Код:
Dim $aAccount[3][2] = _
	[['i_petrov', 'pass1'], _
	 ['v_ivanov', 'pass2'], _
	 ['s_sidorov','pass3']]

For $i = 0 To UBound($aAccount)-1
	GUICtrlSetData($Combo1, $aAccount[$i][0] & '|')
Next
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Я тоже написал небольшой пример.

Код:
#Include <ComboConstants.au3>
#Include <EditConstants.au3>
#Include <GUIComboBox.au3>
#Include <GUIConstantsEx.au3>

Global $Data[3][4] = _
	   [['Иванов',  'Ivanov',  '+79034450911', 'Водолей'], _
		['Петров',  'Petrov',  '+79036780019', 'Рак'], _
		['Сидоров', 'Sidorov', '+79031096788', 'Весы']]

Global $Input[4]

$hForm = GUICreate('MyGUI', 300, 161)
For $i = 0 To 3
	$Input[$i] = GUICtrlCreateInput($Data[0][$i], 10, 10 + 30 * $i, 100, 19, $ES_READONLY)
Next
$Combo = GUICtrlCreateCombo('', 10, 130, 280, 21, $CBS_DROPDOWNLIST)
For $i = 0 To UBound($Data) - 1
	_GUICtrlComboBox_AddString($Combo, $Data[$i][0])
Next
_GUICtrlComboBox_SetCurSel($Combo, 0)
GUISetState()

While 1
	Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE
			ExitLoop
		Case $Combo
			$Index = _GUICtrlComboBox_GetCurSel($Combo)
			For $i = 0 To 3
				GUICtrlSetData($Input[$i], $Data[$Index][$i])
			Next
	EndSwitch
WEnd


Максимум, что может тебе понадобиться для произвольного количества записей, это двумерный массив.
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
Как всегда отличный пример Yashied :ok:
 

AZJIO

Меценат
Меценат
Сообщения
2,892
Репутация
1,196
panda_911
Посмотри _GUICtrlComboBoxEx_SetItemParam. Как и во многих других функциях (_GUICtrlTreeView_SetItemParam, _GUICtrlListView_SetItemParam) это способ присвоить ассоциативный индекс пункту, который можно получить используя _GUICtrlComboBoxEx_GetItemParam.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
AZJIO сказал(а):
Как и во многих других функциях (_GUICtrlTreeView_SetItemParam, _GUICtrlListView_SetItemParam) это способ присвоить ассоциативный индекс пункту...

Для ListView и TreeView этот параметр трогать в AutoIt крайне не рекомендуется, т.к. механизм сообщений использует его для идентификации элемента.
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
Посмотрел в GUIComboBox.au3 функцию _GUICtrlComboBox_GetCurSel(), решил попробовать с GUICtrlSendMsg(), для пробы взял код Yashied`a, вроде работает. :smile:
Код:
#include <ComboConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>

Global $aData[3][4] = _
		[['Иванов', 'Ivanov', '+79034450911', 'Водолей'], _
		['Петров', 'Petrov', '+79036780019', 'Рак'], _
		['Сидоров', 'Sidorov', '+79031096788', 'Весы']]

Global $sDate
Dim $aInput[UBound($aData, 2)]

$hForm = GUICreate('MyGUI', 300, 161)
For $i = 0 To UBound($aInput) - 1
	$aInput[$i] = GUICtrlCreateInput($aData[0][$i], 10, 10 + 30 * $i, 100, 19, $ES_READONLY)
Next
$nCombo = GUICtrlCreateCombo('', 10, 130, 280, 21, $CBS_DROPDOWNLIST)
For $i = 0 To UBound($aData) - 1
	$sDate &= $aData[$i][0] & '|'
Next
GUICtrlSetData(-1, $sDate, $aData[0][0])
$sDate = ''
GUISetState()

While 1
	Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE
			Exit
		Case $nCombo
			$Index = GUICtrlSendMsg($nCombo, $CB_GETCURSEL, 0, 0)
			For $i = 0 To 3
				GUICtrlSetData($aInput[$i], $aData[$Index][$i])
			Next
	EndSwitch
WEnd
 
Автор
P

panda_911

Только вверх, только вперед!
Сообщения
52
Репутация
8
Премного благодарен!
В ходе подгонки кода под свои нужды, узнал много нового!
Теперь все работает.
 

AZJIO

Меценат
Меценат
Сообщения
2,892
Репутация
1,196
Ассоциативные ItemParam ни как не связаны с индексом и ID, причём Get-запрос этого параметра возвращает 0, если он не был установлен. Именно этот параметр и используется в FindParam и возвращает индекс найденного.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Для ListView и TreeView (возможно еще где-нибудь) в "ItemParam" заносится CtrlID этого Item'а во время его создания с помощью функций GUICtrlCreateListViewItem() и GUICtrlCreateTreeViewItem() соответственно. Далее этот "ItemParam" AutoIt использует для внутренней идентификации элемента списка/дерева в разных операциях, например при активации элементов, их раскраске и т.д. Т.к. физически элементы списка/дерева не являются control'ами, а в AutoIt они приравниваются к ним, то подобный функционал достигается именно благодаря этому механизму.

При активации (двойном клике) элемента из любого списка/дерева, AutoIt считывает его "ItemParam" (он же CtrlID) и помещает это значение во внутреннюю очередь сообщений, откуда функция GUIGetMsg() его берет и передает в программу при ее вызове.

Если список/дерево заполняется посредством _GUICtrlListView_* функций, то, естественно, "ItemParam" не затрагивается и будет равен 0, но, т.к. идентификация элементов происходит на уровне функции обработки ("WindowProc"), то в любом случае при активации элемента будет считан его "ItemParam" и помещен в очередь сообщений. А поскольку значение CtrlID не может быть равным 0, то это ни к чему плохому не приведет, GUIGetMsg() просто возвратит 0 или вообще его не воспримет.

Теперь несложно представить, что произойдет, если вы будите использовать в свох программах "ItemParam". Допустим вы поместили в "ItemParam" какого-нибудь элемента значение X. Тогда при активации этого элемента GUIGetMsg() возвратит X. А что, если на форме уже присутствует элемент со значением CtrlID равным X, например "Button"? В этом случае ваша программа воспримет активацию элемента списка/дерева как нажатие на кнопку. Вот вам и она из проблем, связанных с использованием "ItemParam".

На самом деле, здесь все намного сложнее. Для CtrlID в "ItemParam" отведено только младшее слово (вспомните ограничение на количество элементов в AutoIt, равное 65532), старшее слово может использоваться для других целей, но об этом разработчики ничего не говорят.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Чтобы не быть голословным, вот простой пример, демонстрирующий то, что я написал выше:

Код:
#Include <GUIConstantsEx.au3>
#Include <GUIListView.au3>

GUICreate('MyGUI', 220, 307)
$LV = GUICtrlCreateListView('#', 10, 10, 200, 260)
_GUICtrlListView_SetColumnWidth($LV, 0, 60)
For $i = 0 To 4
	_GUICtrlListView_AddItem($LV, 'Item' & $i)
Next
_GUICtrlListView_SetItemParam($LV, 0, 4)
_GUICtrlListView_SetItemParam($LV, 1, -3)
$Button = GUICtrlCreateButton('Button', 70, 276, 80, 25)
GUISetState()

While 1
	Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE
			Exit
		Case $Button
			MsgBox(0, '', 'Button has been pressed!')
	EndSwitch
WEnd


Попробуйте выделить в списке "Item0" или "Item1"...

:smile:
 

AZJIO

Меценат
Меценат
Сообщения
2,892
Репутация
1,196
Решился всё таки я сделать ассоциативный комбо

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

Global $a[11][3] = [ _
		[10, 12, 10], _
		[1, 'текст 1', 1234], _
		[2, 'Привет', 390], _
		[3, 'ага', 879], _
		[4, 'второе', 45678], _
		[5, 'вчера', 8], _
		[6, 'код', 3], _
		[7, 'автоит', 6787], _
		[8, 'пример', 0365], _
		[9, 'асоцир', 3262], _
		[10, 'конец', 6554]]

$hGUI = GUICreate("Ассоциативный комбо", 300, 200)
$hCombo = _GUICtrlComboBoxEx_Create($hGUI, "", 42, 42, 90, 300)

For $i = 1 To $a[0][0]
	_GUICtrlComboBoxEx_AddString($hCombo, $a[$i][1])
	_GUICtrlComboBoxEx_SetItemParam($hCombo, $i - 1, $i)
Next

$StatusBar = GUICtrlCreateLabel('', 5, 5, 190, 17)

GUISetState()
GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")

While 1
	$msg = GUIGetMsg()
	Switch $msg
		Case -3
			Exit
	EndSwitch
WEnd

Func WM_COMMAND($hWnd, $iMsg, $iwParam, $ilParam)
	#forceref $hWnd, $iMsg
	Local $hWndFrom, $iIDFrom, $iCode
	$hWndFrom = $ilParam
	$iIDFrom = BitAND($iwParam, 0xFFFF) ; Low Word
	$iCode = BitShift($iwParam, 16) ; Hi Word
	Switch $hWndFrom
		Case $hCombo
			Switch $iCode
				Case $CBN_SELCHANGE
					$ind = _GUICtrlComboBoxEx_GetCurSel($hCombo)
					If $ind <> -1 Then
						$indAr = _GUICtrlComboBoxEx_GetItemParam($hCombo, $ind)
						GUICtrlSetData($StatusBar, $a[$indAr][0] & ', ' & $a[$indAr][1] & ', ' & $a[$indAr][2])
					EndIf
			EndSwitch
	EndSwitch
	Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_COMMAND
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
AZJIO,
Точно также работает, только код проще. :smile:
Код:
#include <GUIConstantsEx.au3>
#include <ComboConstants.au3>

Global $aData[11][3] = [ _
		[10, 12, 10], _
		[1, 'текст 1', 1234], _
		[2, 'Привет', 390], _
		[3, 'ага', 879], _
		[4, 'второе', 45678], _
		[5, 'вчера', 8], _
		[6, 'код', 3], _
		[7, 'автоит', 6787], _
		[8, 'пример', 0365], _
		[9, 'асоцир', 3262], _
		[10, 'конец', 6554]], $sDate

$hGUI = GUICreate('Ассоциативный комбо', 300, 200)
$nCombo = GUICtrlCreateCombo('', 10, 130, 280, 21, $CBS_DROPDOWNLIST)
For $i = 1 To UBound($aData) - 1
	$sDate &= $aData[$i][1] & '|'
Next
GUICtrlSetData(-1, $sDate, $aData[0][0])
$sDate = ''
$StatusBar = GUICtrlCreateLabel('', 5, 5, 190, 17)
GUISetState()

While 1
	Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE
			Exit
		Case $nCombo
			$Index = GUICtrlSendMsg($nCombo, $CB_GETCURSEL, 0, 0)
			$Index += 1
			GUICtrlSetData($StatusBar, $aData[$Index][0] & ', ' & $aData[$Index][1] & ', ' & $aData[$Index][2])
	EndSwitch
WEnd
 

AZJIO

Меценат
Меценат
Сообщения
2,892
Репутация
1,196
madmasles
Точно также работает, только код проще.
Если список не сортируется или не удаляются элементы списка, то да. То есть индексы соответствуют индексам массива.

В моём варианте чисто по ассоциативному параметру.
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
AZJIO [?]
Если список не сортируется или не удаляются элементы списка, то да.
Сделать пример с сортировкой и удалением?
Код:
#include <GUIConstantsEx.au3>
#include <ComboConstants.au3>
#include <Array.au3>

Global $aData[11][3] = [ _
		[10, 12, 10], _
		[1, 'текст 1', 1234], _
		[2, 'Привет', 390], _
		[3, 'ага', 879], _
		[4, 'второе', 45678], _
		[5, 'вчера', 8], _
		[6, 'код', 3], _
		[7, 'автоит', 6787], _
		[8, 'пример', 0365], _
		[9, 'асоцир', 3262], _
		[10, 'конец', 6554]], $sDate

$hGUI = GUICreate('Ассоциативный комбо', 300, 200)
$nCombo = GUICtrlCreateCombo('', 10, 130, 280, 21, $CBS_DROPDOWNLIST)
For $i = 1 To UBound($aData) - 1
	$sDate &= $aData[$i][1] & '|'
Next
GUICtrlSetData(-1, $sDate)
$sDate = ''
$StatusBar = GUICtrlCreateLabel('', 5, 5, 190, 17)
$nButton = GUICtrlCreateButton('Click me', 100, 50, 100, 30)
GUISetState()

While 1
	Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE
			Exit
		Case $nButton
			If Random(0, 1, 1) Then
				If UBound($aData) > 3 Then
					_ArrayDelete($aData, Random(1, UBound($aData) - 1, 1))
					ConsoleWrite('Delete' & @LF)
				EndIf
			Else
				_ArraySort($aData, 0, 1, 0, Random(0, 2, 1))
				ConsoleWrite('Sort' & @LF)
			EndIf
			GUICtrlSetData($nCombo, '')
			GUICtrlSetData($StatusBar, '')
			For $i = 1 To UBound($aData) - 1
				$sDate &= $aData[$i][1] & '|'
			Next
			GUICtrlSetData($nCombo, $sDate)
			$sDate = ''
		Case $nCombo
			$Index = GUICtrlSendMsg($nCombo, $CB_GETCURSEL, 0, 0)
			$Index += 1
			GUICtrlSetData($StatusBar, $aData[$Index][0] & ', ' & $aData[$Index][1] & ', ' & $aData[$Index][2])
	EndSwitch
WEnd
 
Верх