Что нового

[Массивы] Наполнение "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
Репутация
964
Логичнее будет выбирать 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 714
Я тоже написал небольшой пример.

Код:
#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
Репутация
964
Как всегда отличный пример Yashied :ok:
 

AZJIO

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

Yashied

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

madmasles

Модератор
Глобальный модератор
Сообщения
7 790
Репутация
2 320
Посмотрел в 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 752
Репутация
1 149
Ассоциативные ItemParam ни как не связаны с индексом и ID, причём Get-запрос этого параметра возвращает 0, если он не был установлен. Именно этот параметр и используется в FindParam и возвращает индекс найденного.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 714
Для 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 714
Чтобы не быть голословным, вот простой пример, демонстрирующий то, что я написал выше:

Код:
#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 752
Репутация
1 149
Решился всё таки я сделать ассоциативный комбо

Код:
#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 320
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 752
Репутация
1 149
madmasles
Точно также работает, только код проще.
Если список не сортируется или не удаляются элементы списка, то да. То есть индексы соответствуют индексам массива.

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

madmasles

Модератор
Глобальный модератор
Сообщения
7 790
Репутация
2 320
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
 
Верх