VBobCat VBobCat - 2 days ago 4
Vb.net Question

Detect when TextBox autocomplete list is showing

I have TextBoxes and associated Timers that restarts on each keydown or mouseclick event, and performs queries based on typed text after 3 seconds without those events. So far so good.

But some of my TextBoxes also have AutoComplete lists which user can browse in, but even if they do using keyboard arrow keys, timer is not halted and an unexpected query is fired in the middle of user browsing the list.

Question: is there a way of detecting when autocomplete list is showing, so that I can suspend timer or ignoring its tick?

Thank you very much!

Answer

You can use EnumThreadWindows to find all auto complete dropdown windows and check if any of them is visible. The Auto-complete dropdown window class name is Auto-Suggest Dropdown. You can use GetClassName method to get class name of enumerated windows and then using IsWindowVisible method check if the window is visible.

Example

In below example, I used a timer like you have in your code in the question, and in tick event of the timer, I've checked if there is an auto-complete window open I showed "Open" in title of form, otherwise showed "close":

Delegate Function EnumThreadDelegate(hWnd As IntPtr, lParam As IntPtr) As Boolean

<System.Runtime.InteropServices.DllImport("user32.dll")> _
Shared Function EnumThreadWindows(dwThreadId As Integer, _
    lpfn As EnumThreadDelegate, lParam As IntPtr) As Boolean
End Function

<System.Runtime.InteropServices.DllImport("user32.dll")> _
Shared Function GetClassName(ByVal hWnd As System.IntPtr,
    lpClassName As System.Text.StringBuilder, _
    nMaxCount As Integer) As Integer
End Function

<System.Runtime.InteropServices.DllImport("kernel32.dll")> _
Shared Function GetCurrentThreadId() As Integer
End Function

<System.Runtime.InteropServices.DllImport("user32.dll")> _
Shared Function IsWindowVisible(hWnd As IntPtr) As Boolean
End Function

Const AutoCompleteClassName As String = "Auto-Suggest Dropdown"
Function EnumThreadCallback(hWnd As IntPtr, lParam As IntPtr) As Boolean
    Dim className As New System.Text.StringBuilder("", 256)
    GetClassName(hWnd, className, 256)
    If className.ToString() = AutoCompleteClassName AndAlso IsWindowVisible(hWnd) Then
        AnAutoCOmpleteIsOpen = True
    End If
    Return True
End Function
Dim AnAutoCOmpleteIsOpen As Boolean = False
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    AnAutoCOmpleteIsOpen = False
    EnumThreadWindows(GetCurrentThreadId(), _
        New EnumThreadDelegate(AddressOf Me.EnumThreadCallback), IntPtr.Zero)
    If (AnAutoCOmpleteIsOpen) Then
        Me.Text = "Open"
    Else
        Me.Text = "Close"
    End If
End Sub
Comments