Что нового

[Окна, Диалоги] Как получить доступ к ячейкам элемента Grid языка Visual Basic

Okseen

Новичок
Сообщения
8
Репутация
0
Добрый день.
Есть программа написанная на Visual Basic. Есть главное окно программы и собственно в этом окне есть форма VB на которой расположены управляющие элементы (кнопки, лейблы и собственно элемент Grid (таблица) ).
Вопрос такой: можно ли как то получить информацию об ячейках данной таблицы - Win Info не определяет ячейки таблицы как какой то отдельный элемент.

P.S. Чего именно я хочу добиться - как то "захватить" ячейку этой таблицы и эмулировать двойное нажатие на эту ячейку.
Спасибо.
 

InnI

AutoIT Гуру
Сообщения
4,950
Репутация
1,445
Okseen
получить информацию об ячейках данной таблицы
Попробуйте UIAutomate. Если утилита Inspect различит ячейки, как отдельные элементы, то можно использовать эту UDF для доступа к ним.

эмулировать двойное нажатие на эту ячейку
Если положение ячейки известно, то можно попробовать ControlClick() по координатам Grid.
 
Автор
O

Okseen

Новичок
Сообщения
8
Репутация
0
Попробуйте UIAutomate. Если утилита Inspect различит ячейки, как отдельные элементы, то можно использовать эту UDF для доступа к ним.

Спасибо попробую )

Если положение ячейки известно, то можно попробовать ControlClick() по координатам Grid.

Да про ControlClick() я знаю, просто если бы была возможность так сказать "привязаться" к конкретной ячейке чтобы даже при изменении положения окна я мог совершать с ней определенные действия.
 

InnI

AutoIT Гуру
Сообщения
4,950
Репутация
1,445
Okseen
даже при изменении положения окна
ControlClick() использует координаты относительно левого верхнего угла элемента. Поэтому изменение положения окна на эти координаты не влияют.
 
Автор
O

Okseen

Новичок
Сообщения
8
Репутация
0
Попробовал я UIAutomate и Inspector но ячейки по отдельности не распознаются :(
И еще такой вопрос - как работать со свойствами объекта UIAutomate ?

Допустим я создал объект по конкретному handl-у, но я не могу никак вывести свойство IsEnabled этого объекта в консоль. Хотя в инспекторе показывается что данное свойство есть.
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
IsEnabled такого точного свойства нету. inspect получает его методом GetCurrentPropertyValue указанного элемента.
Тебе нужно делать так:
Код:
Local $vValue = 0
$oElement.GetCurrentPropertyValue($UIA_IsEnabledPropertyId, $vValue)
ConsoleWrite('IsEnabled: ' & $vValue & @CRLF)

Или через функцию _UIA_ElementGetPropertyValue которую написал InnI
Код:
_UIA_ElementGetPropertyValue($oElement,$UIA_IsEnabledPropertyId)
 
Автор
O

Okseen

Новичок
Сообщения
8
Репутация
0
Вот показываю на примере - это показал Инспектор:
How found: Mouse move (660,153)
hwnd=0x003121B6 32bit class="ComboLBox" style=0x54A08111 ex=0x88
RuntimeId: "[42.3219894.2.-2147483647.3219894.-4.23]"
BoundingRectangle: {l:528 t:148 r:698 b:164}
ProcessId: 12176
ControlType: UIA_ListItemControlTypeId (0xC357)
LocalizedControlType: "элемент списка"
Name: ""
AccessKey: ""
HasKeyboardFocus: false
IsKeyboardFocusable: true
IsEnabled: true
HelpText: ""
IsPassword: false
IsOffscreen: false
ProviderDescription: "[pid:12176,hwnd:0x0 Annotation:Microsoft: Annotation Proxy (unmanaged:uiautomationcore.dll); Main(parent link):Microsoft: MSAA Proxy (unmanaged:uiautomationcore.dll)]"
SelectionItem.IsSelected: true
SelectionItem.SelectionContainer: "" список
LegacyIAccessible.ChildId: 23
LegacyIAccessible.DefaultAction: "Двойной щелчок"
LegacyIAccessible.Description: ""
LegacyIAccessible.Help: ""
LegacyIAccessible.KeyboardShortcut: ""
LegacyIAccessible.Name: ""
LegacyIAccessible.Role: элемент списка (0x22)
LegacyIAccessible.State: выделенный,фокусируемое,выделяемое (0x300002)
LegacyIAccessible.Value: ""
IsDockPatternAvailable: false
IsExpandCollapsePatternAvailable: false
IsGridItemPatternAvailable: false
IsGridPatternAvailable: false
IsInvokePatternAvailable: true
IsLegacyIAccessiblePatternAvailable: true
IsMultipleViewPatternAvailable: false
IsRangeValuePatternAvailable: false
IsScrollPatternAvailable: false
IsScrollItemPatternAvailable: true
IsSelectionItemPatternAvailable: true
IsSelectionPatternAvailable: false
IsTablePatternAvailable: false
IsTableItemPatternAvailable: false
IsTextPatternAvailable: false
IsTogglePatternAvailable: false
IsTransformPatternAvailable: false
IsValuePatternAvailable: false
IsWindowPatternAvailable: false
IsItemContainerPatternAvailable: false
IsVirtualizedItemPatternAvailable: false
IsSynchronizedInputPatternAvailable: false
FirstChild: [null]
LastChild: [null]
Next: "" элемент списка
Previous: "" элемент списка
Other Props: Object has no additional properties
Children: Container has no children
Ancestors: "" список
"Рабочий стол" панель
[ No Parent ]

Видно что class=ComboBox и есть свойство LegacyIAccessible.ChildId и LegacyIAccessible.Role которые как я понял обозначают элемент списка.
Можно ли как то программно нажать допустим на первый элемент этого списка ?
Спасибо
 

InnI

AutoIT Гуру
Сообщения
4,950
Репутация
1,445
Okseen
UDF UIAutomate была задумана, как дополнительная возможность по работе с нестандартными элементами. ComboBox - это стандартный элемент. Его "видит" Au3Info. Следовательно проще (и лучше) использовать стандартные функции AutoIt
Код:
ControlCommand("Заголовок окна", "", "ComboBox1", "SelectString", "Текст строки")


А теперь как это сделать через UDF:
1. Найти ComboBox
2. Раскрыть ComboBox (чтобы раскрыть нужно либо использовать Expand, либо найти и кликнуть кнопку со стрелкой)
3. Найти в выпавшем списке нужный пункт и выбрать его

Поэтому я вам очень рекомендую по максимуму использовать стандартные функции и стандартные UDF.
 
Автор
O

Okseen

Новичок
Сообщения
8
Репутация
0
UDF UIAutomate была задумана, как дополнительная возможность по работе с нестандартными элементами. ComboBox - это стандартный элемент. Его "видит" Au3Info. Следовательно проще (и лучше) использовать стандартные функции AutoIt
Код:
ControlCommand("Заголовок окна", "", "ComboBox1", "SelectString", "Текст строки")

С этим разобрался немного.
Но теперь возникла новая (старая новая) :
Код:
How found:	Mouse move (142,70)
	hwnd=0x00890F72 32bit class="ThunderRT6FormDC" style=0x56CC0000 ex=0x40140
RuntimeId:	"[42.8982386.1.-2147483647.8982386.-2.0]"
BoundingRectangle:	{l:29 t:66 r:1352 b:88}
ProcessId:	12176
ControlType:	UIA_TitleBarControlTypeId (0xC375)
LocalizedControlType:	"название"
HasKeyboardFocus:	false
IsKeyboardFocusable:	true
IsEnabled:	true
IsContentElement:	false
IsPassword:	false
IsOffscreen:	false
ProviderDescription:	"[pid:11952,hwnd:0x0 Annotation:Microsoft: Annotation Proxy (unmanaged:uiautomationcore.dll); Main(parent link):Microsoft: MSAA Proxy (unmanaged:uiautomationcore.dll)]"
Value.IsReadOnly:	false
Value.Value:	"Журнал менеджера"
LegacyIAccessible.ChildId:	0
LegacyIAccessible.Description:	"Выводит заголовок окна и элементы управления окном"
LegacyIAccessible.Role:	заголовок (0x1)
LegacyIAccessible.State:	фокусируемое (0x100000)
LegacyIAccessible.Value:	"Журнал менеджера"
IsDockPatternAvailable:	false
IsExpandCollapsePatternAvailable:	false
IsGridItemPatternAvailable:	false
IsGridPatternAvailable:	false
IsInvokePatternAvailable:	false
IsLegacyIAccessiblePatternAvailable:	true
IsMultipleViewPatternAvailable:	false
IsRangeValuePatternAvailable:	false
IsScrollPatternAvailable:	false
IsScrollItemPatternAvailable:	false
IsSelectionItemPatternAvailable:	false
IsSelectionPatternAvailable:	false
IsTablePatternAvailable:	false
IsTableItemPatternAvailable:	false
IsTextPatternAvailable:	false
IsTogglePatternAvailable:	false
IsTransformPatternAvailable:	false
IsValuePatternAvailable:	true
IsWindowPatternAvailable:	false
IsItemContainerPatternAvailable:	false
IsVirtualizedItemPatternAvailable:	false
IsSynchronizedInputPatternAvailable:	false
FirstChild:	"Система" строка меню
LastChild:	"Закрыть" кнопка
Next:	[null]
Previous:	"" панель
Other Props:	Object has no additional properties
Children:	"Система" строка меню
	"Закрыть" кнопка
Ancestors:	"Журнал менеджера" окно
	"Рабочее пространство" панель
	"Sirius Virtual Assistant" окно
	"Рабочий стол" панель
	[ No Parent ]

Могу ли я как то получить доступ к элементам этой формы ? И конкретно интересуют ячейки элемента Grid
 

InnI

AutoIT Гуру
Сообщения
4,950
Репутация
1,445
Okseen
доступ к элементам этой формы
Это не форма, это ЗАГОЛОВОК формы. Чтобы получить информацию о форме - наведите курсор на её боковую или нижнюю рамку. Но информация о форме вам не поможет. Вам нужна информация об её элементах. Вот здесь Ответ #37 я объяснял, как пользоваться Inspect. Только там был сайт, а у вас приложение. Для Inspect - никакой разницы. Интерфейс каждой программы индивидуален и требует изучения. Помогать "вслепую" очень тяжело.

интересуют ячейки элемента Grid
Я вам уже говорил - если Inspect определяет ячейки, как отдельные элементы. Другими словами, при перемещении курсора над ячейками информация в окне Inspect должна меняться на каждой ячейке. Если над разными ячейками информация одинаковая (и соответствует элементу Grid), то информацию с этих ячеек не получить.
 
Автор
O

Okseen

Новичок
Сообщения
8
Репутация
0
Нашел супер костыльный способ решения своей проблемы - перемещаться по таблице стрелками ВВЕРХ, ВНИЗ, ВПРАВО, ВЛЕВО.
Но как то он мне не нравится ))
Такой вопрос - можно как то получить идентификатор ячейки таблицы ? Может средствами WinAPI попробовать, не знаю - все советы уже перечитал, перепробовал.
Я вам уже говорил - если Inspect определяет ячейки, как отдельные элементы. Другими словами, при перемещении курсора над ячейками информация в окне Inspect должна меняться на каждой ячейке. Если над разными ячейками информация одинаковая (и соответствует элементу Grid), то информацию с этих ячеек не получить.

Насчет этого да - не меняется информация, может есть какие то другие программные способы получить ячейки как отдельные элементы ?
Спасибо.
 

InnI

AutoIT Гуру
Сообщения
4,950
Репутация
1,445
Okseen
Нашел супер костыльный способ
Когда ничего не помогает, любой "костыль" - это решение проблемы.

он мне не нравится
Эмоции в решении проблемы не помогут.

Весь AutoIt - это сплошное WinAPI. Все функции, которыми вы пользуетесь, внутренние или UDF - все они используют WinAPI. Только загрузка системы происходит через BIOS, всё остальное - WinAPI.

может есть какие то другие программные способы получить ячейки как отдельные элементы
Уверен, что они есть. Например, создание dll на VB, внедрение её в процесс и перехват/чтение определённых данных. Вероятно, можно ещё в памяти программы поковыряться... это умеют специалисты по игровым ботам. Есть ещё способы прямого чтения с экрана пикселей, контрольных сумм областей, OCR.

Теперь по теме.
Вы не предоставляете никакой информации. Ни названия программы, ни скриншотов, ничего. Даже отчёт Inspect выглядит отредактированным (нет имён пунктов меню, удалено дерево Ancestors и т.д.). Вот как вам помогать?!
Предлагаю следующие варианты. Скорее всего ячейки в элементе Grid имеют одинаковый размер. Следовательно, можно высчитать расстояние между ними и рассчитывать координаты для ControlClick(). Если ячейки динамически меняют размеры, то можно искать пиксели границ по цвету и рассчитывать ширину/высоту. Если ячейки имеют определённые размеры с определёнными данными, то можно искать их по контрольной сумме пикселей или по "картинке". Но если есть полоса прокрутки, то всё усложняется в разы. И лучший способ будет тот, который вам не нравится, а именно перебор ячеек клавишами с клавиатуры.

Если у кого есть ещё идеи - не стесняйтесь, предлагайте.
 
Автор
O

Okseen

Новичок
Сообщения
8
Репутация
0
Вот тут http://prntscr.com/6v0gp6 сама прога. "Журнал менеджера" - это есть форма VB на которой расположен элемент Grid

Вот http://prntscr.com/6v0hdk и http://prntscr.com/6v0hr1 - результаты инспектора - но при нажатии на любую ячейку информация не меняется. И да есть полоса прокрутки.
Доступа к коду программы у естественно нет.

"Вероятно, можно ещё в памяти программы поковыряться" - над этим тоже думал, но к сожалению не знаю как и с чего начинать ))
 

InnI

AutoIT Гуру
Сообщения
4,950
Репутация
1,445
Okseen
при нажатии на любую ячейку информация не меняется
Вы это повторяете уже в третий раз. От количества повторений доступ к ячейкам не изменится. Как его нет, так и не будет.
Теперь, обладая визуальным представлением, попробуйте объяснить - что вы хотите сделать? Какие действия вы хотите автоматизировать?
 
Автор
O

Okseen

Новичок
Сообщения
8
Репутация
0
Хочу считать данные со столбцов Описание, Статус заказа и Сумма по определенным условиям (поиск описания по шаблону, статус должен быть "Не обработан" и сумма > 5000). И для тех ячеек для которых эти условия выполняются я хочу менять статус заказа.
Статус заказа это выпадающий список - открывается по двойному клику мыши.
 

InnI

AutoIT Гуру
Сообщения
4,950
Репутация
1,445
Okseen
Описание, Статус заказа и Сумма
Статус заказа: поиск красного пикселя в определённой области
Код:
PixelSearch()
или вычисление контрольной суммы пикселей в определённой области и сравнение с заранее известной
Код:
PixelChecksum()
Описание и Сумма: Оптическое распознавание символов

к сожалению не знаю как и с чего начинать
Когда к элементам интерфейса нет доступа, программа становится похожей на игру. Разработкой игровых ботов занимаются здесь: Разработка ботов. Там и поиск пикселей и работа с памятью. В вашем случае даже проще - нет защиты от несанкционированных действий. Только специалисты по играм, возможно, смогут вам помочь.
Вот для них будет "вызов" - сделать игрового бота для банального окна. Хотя, думаю, им это будет просто не интересно.

Okseen, вы поймите, что AutoIt не всесилен. Есть некоторые моменты, которые (пока) машинному анализу не подвластны или требуют значительных затрат на разработку. И некоторые интерфейсы, к сожалению, рассчитаны только на людей, потому что разработчики не хотят (именно не хотят, т.е. могут, но не хотят) обеспечивать возможность автоматизации собственных приложений.
 
Верх