Имя элемента управления из другого окна
Мне нужно прочитать текстовое значение из другого окна и запросить это значение в другом приложении (мой вопрос будет касаться 1-го задания)… поэтому я "шпионю" за другим окном (какое-то стороннее приложение, которое мы используем в связи с нашим продуктом) и ожидание нажатия кнопки "принять" для считывания значения из текстового поля. Это другое приложение, диалоговое окно, имеет несколько текстовых полей и командных кнопок. Я сделал крючок мыши и активирую его при появлении этого приложения. Я читаю все движения мыши внутри этого прямоугольника окна; тексты, подписи, идентификаторы дочерних окон, прямоугольники, щелчки левой / правой / средней / колесики. Я могу получить кнопку "принять"; Я МОГУ ВИДЕТЬ заголовок кнопки и могу прочитать это окно, получить текст и определить, какая кнопка нажата и т. Д. Теперь... Я могу читать ВСЕ значения класса РЕДАКТИРОВАТЬ, получать их дескрипторы окон, прямоугольники и т. Д., НО НЕ МОГУ ОПРЕДЕЛИТЬ ИХ КАК УНИКАЛЬНЫЕ предметы в коллекции классов: мне нужно специально прочитать желаемое значение текстового поля. К счастью, текстовое поле, которое меня интересует, ВСЕГДА НАХОДИТСЯ ПЕРВОЙ В МОЕЙ ПЕТЛЕ, когда я читаю тексты из цикла EDIT. Однако я хотел бы быть более конкретным; убедившись, что я читаю текстовое поле с именем. Я знаю. Во время разработки я мог прочитать это ИМЯ и жестко запрограммировать его в программе. Я подозреваю, что имя элемента управления не сохраняется в двоичном коде. Насколько я понимаю, идентификатор элемента управления, дескриптор окна создаются при создании окна и не имеют абсолютно никакой ссылки на имя элемента управления (скажем, txtOrderNumber). Если для кнопок я могу быть конкретным из-за заголовков кнопок (так, я могу определить, какая кнопка нажата), я заблокирован с элементами класса EDIT и брошен в 1-е предположение при чтении значения. Мой вопрос: как я могу получить имя элемента управления из другого окна, для этой задачи мне интересно узнать об именах экземпляров класса EDIT. Вот некоторые коды (сокращенные) из проекта:
Dim hWnd As IntPtr = FindWindow (Nothing, _windowText)
API: FindWindowEx API: SendMessage API: GetClassName API: GetWindowTextLength API: GetWindowText API: WM_GETTEXT
Public Shared Function GetClassValues(_controlClass As String, _hWindow As IntPtr) As List(Of String)
Dim cl As New List(Of String)
'First control handle in that class
Dim hc As IntPtr = FindWindowEx(_hWindow, IntPtr.Zero, _controlClass, vbNullString)
Do
Dim sv As String = GetWindowValue(hc)
cl.Add(sv)
'Next control (after hc) handle
hc = FindWindowEx(_hWindow, hc, _controlClass, vbNullString)
Loop Until hc = 0
Return cl
End Function
Public Shared Function GetWindowValue(_hWindow As IntPtr) As String
If _hWindow = IntPtr.Zero Then Return String.Empty
Dim sz As Integer = 256
Dim bf As IntPtr = Marshal.AllocHGlobal(sz)
Dim pt As IntPtr = SendMessage(_hWindow, WM_GETTEXT, sz, bf)
Dim rs As String = Marshal.PtrToStringUni(bf)
Marshal.Release(bf)
Return rs.Trim
End Function
Public Shared Function GetWindowClassName(_hWindow As IntPtr) As String
Dim ln As Integer = 256
Dim sb As New System.Text.StringBuilder("", ln)
GetClassName(_hWindow, sb, ln)
Return sb.ToString()
End Function
Public Shared Function GetWindowText(_hWindow As IntPtr) As String
Dim ln As Integer
If _hWindow.ToInt32 <= 0 Then Return String.Empty
ln = GetWindowTextLength(_hWindow)
If ln = 0 Then Return String.Empty
Dim sb As New System.Text.StringBuilder("", ln + 1)
GetWindowText(_hWindow, sb, sb.Capacity)
Return sb.ToString()
End Function
Я посмотрел на API GetWindowLong и GetDlgCtrlID и попробовал большинство флагов, но пока безуспешно...
Любой совет, подсказка, направление приветствуется. Спасибо
1 ответ
Я сделал глобальный хук мыши, это не проблема, и GetWindowText и WM_GETTEXT работают нормально. На самом деле программа работает нормально и функционально на данный момент. После обнаружения целевого окна я сохраняю дескрипторы дочерних окон в коллекции списков, используя API EnumChildWindows и фильтруя только окна класса EDIT (используется в связи с опубликованной выше измененной версией функции GetClassValues. Аргументом для этой функции является первый дескриптор окна класса EDIT). В любом случае, способ произвольного доступа к желаемому текстовому полю - использовать сохраненный список для окон этого класса и доступ по индексу списка. Как я упоминал ранее, к счастью, окна СОЗДАЮТ ЭТОГО РЕБЕНКА в последовательном порядке. Итак, в моем случае это окно класса EDIT, текстовое поле "объект", всегда является первым в списке, хотя в главном окне их много. Я хотел бы получить это имя текстового поля "объект", скажем "txtAccountNumber", как я упоминал ранее...