2017-02-18 100 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獲取項目文本和計數。在你測試之後,如果你喜歡答案,可以投下贊成票。我會在答案中保存一個虛擬變化,讓你改變你的投票;) –