2017-02-18 88 views
0

我想获得一个计数和列表ComboBox控制这不是我的,所以我不能修改代码。检索ComboBox通过使用SendMessage API计数和项目

例如,通过使用SendMessage API可以控制目标应用程序。

但是,如何通过挂钩检索目标控件的整个列表?

+0

可以使用UI自动化 –

+0

[GetComboBoxInfo](https://msdn.microsoft.com/en-us /library/windows/desktop/bb775939(v=vs.85).aspx)并使用[COMBOBOXINFO]中的'hwndList'(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类,你可以通过传递ComboBoxHandle创建它的实例,并使用其属性:

  • SelectedIndexInteger:选择指数返回,返回 - 1如果没有选择项目。
  • Selectedtext作为String:返回所选项目的文本,如果未选择项目,则返回String.Empty
  • ItemsCount as Integer:返回项目数。
  • Items(index)String:返回文本中指定的项目(在指定索引的项目)
  • ItemsList(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

@IInspectable不要太急于downvote的答案。首先测试它们。我使用两种不同的流程对其进行了测试,并且它可以正常工作:) –

+1

@IInspectable您可以使用2个不同的应用程序对其进行简单测试,其中一个包含组合框,另一个使用我的ComboBoxHelper获取项目文本和计数。在你测试之后,如果你喜欢答案,可以投下赞成票。我会在答案中保存一个虚拟变化,让你改变你的投票;) –