2017-02-18 15 views
0

Я хочу получить счет и список управления ComboBox, который не является моим, поэтому я не могу изменить код.Получить счетчик ComboBox и элементы с помощью API SendMessage

Например, для управления целевым приложением можно использовать API SendMessage.

Но как я могу получить весь список целевого элемента управления, подключив его?

+0

Вы можете использовать UI Automation –

+0

[GetComboBoxInfo] (https://msdn.microsoft.com/en-us /library/windows/desktop/bb775939(v=vs.85).aspx) и использовать 'hwndList' из [COMBOBOXINFO] (https://msdn.microsoft.com/en-us/library/windows/desktop/bb775798 (v = vs.85) .aspx)? – RbMm

+0

Вы перешлите свое предложенное решение в описание проблемы. Пожалуйста, спросите о проблеме, которую вы пытаетесь решить. Это означает удаление всех ссылок на * «SendMessage» * и * «hooking» *. – IInspectable

ответ

2

Вы можете найти список ComboBox управляющих сообщений здесь:

Чтобы получить число пунктов вам нужно использовать CB_GETCOUNT сообщение и получить текст элемента вы можно использовать CB_GETLBTEXT сообщение.

Пример

Здесь я создал ComboBoxHelper класс, который вы можете создать его экземпляр, передав Handle в ComboBox и использовать его свойства:

  • SelectedIndex в Integer: Возвращает выбранный индекс, возвращается - 1, если элемент не выбран.
  • Selectedtext как String: Возвращает текст выбранного элемента, возвращает String.Empty, если элемент не выбран.
  • ItemsCount as Integer: возвращает количество элементов.
  • Items(index) в String: возвращает текст указанного элемента (пункт, по указанному индексу)
  • Items как List(of String): возвращает список элементов из выпадающего списка. Если элементов нет, он возвращает пустой список.
Public Class ComboBoxHelper 
    Private hWnd As IntPtr 
    Const CB_GETCURSEL As Integer = &H147 
    Const CB_SETCURSEL As Integer = &H14E 
    Const CB_GETCOUNT As Integer = &H146 
    Const CB_GETLBTEXT As Integer = &H148 
    Const CB_GETLBTEXTLEN As Integer = &H149 
    <System.Runtime.InteropServices.DllImport("user32.dll")> _ 
    Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As Integer, _ 
     ByVal wParam As Integer, ByRef lParam As Integer) As IntPtr 
    End Function 
    <System.Runtime.InteropServices.DllImport("user32.dll")> _ 
    Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As Integer, _ 
     ByVal wParam As Integer, ByVal lParam As System.Text.StringBuilder) As IntPtr 
    End Function 
    Public Sub New(handle As IntPtr) 
     hWnd = handle 
    End Sub 
    Public Property SelectedIndex As Integer 
     Get 
      Return SendMessage(hWnd, CB_GETCURSEL, 0, 0).ToInt32() 
     End Get 
     Set(ByVal value As Integer) 
      SendMessage(hWnd, CB_SETCURSEL, value, 0).ToInt32() 
     End Set 
    End Property 
    Public ReadOnly Property ItemsCount As Integer 
     Get 
      Return SendMessage(hWnd, CB_GETCOUNT, 0, 0).ToInt32() 
     End Get 
    End Property 
    Public ReadOnly Property SelectedText As String 
     Get 
      Dim index = Me.SelectedIndex 
      If (Me.SelectedIndex = -1) Then 
       Return String.Empty 
      End If 
      Return Me.Items(index) 
     End Get 
    End Property 
    Public ReadOnly Property Items() As List(Of String) 
     Get 
      If (ItemsCount > 0) Then 
       Return Enumerable.Range(0, ItemsCount) _ 
           .Select(Function(index) Items(index)).ToList() 
      Else 
       Return New List(Of String) 
      End If 
     End Get 
    End Property 
    Public ReadOnly Property Items(index As Integer) As String 
     Get 
      If (index < 0 OrElse index >= ItemsCount) Then 
       Throw New ArgumentOutOfRangeException("index") 
      End If 
      Dim length = SendMessage(hWnd, CB_GETLBTEXTLEN, index, 0).ToInt32() 
      Dim text As New System.Text.StringBuilder(length) 
      SendMessage(hWnd, CB_GETLBTEXT, index, text) 
      Return text.ToString() 
     End Get 
    End Property 
End Class 

Ниже приведен пример использования класса:

Dim combo As New ComboBoxHelper(hWnd) 'You have hWnd 
MessageBox.Show(combo.ItemsCount.ToString()) 
MessageBox.Show(combo.SelectedIndex.ToString()) 
MessageBox.Show(combo.SelectedText.ToString()) 
combo.Items.ForEach(Function(item) MessageBox.Show(item)) 
+0

Вы не можете отправить 'CB_GETLBTEXT' через границы процесса (или любое личное сообщение класса окна, если на то пошло). Извините, не решение. -1. – IInspectable

+1

@Инспективный Не спешите отвечать на нижестоящие ответы. Сначала проверьте их. Я тестировал его, используя два разных процесса, и он работает нормально. –

+1

@IInspectable. Вы можете просто протестировать его, используя два разных приложения, один из которых содержит выпадающий список, а другой использовал мой ComboBoxHelper для получения текста и подсчета предметов. После того, как вы проверите его, добавьте вверх, если вам понравился ответ. Я сохраню фиктивное изменение в ответе, чтобы вы могли изменить свой голос;) –