我有TextBox
个控件和关联的计时器,它们会在每个KeyDown
或MouseClick
事件上重新启动,并在没有这些事件的情况下在3秒后根据键入的文本执行查询。到目前为止一切都很好。
但我的一些TextBox还有自动完成列表,用户可以浏览,但即使他们使用键盘箭头键,也不会停止计时器,并且在浏览列表的用户中间会触发意外查询。
问题:有没有办法检测自动填充列表何时显示,以便我可以暂停计时器或忽略其勾号?
非常感谢!
答案 0 :(得分:3)
您可以使用EnumThreadWindows
查找所有自动完成下拉窗口,并检查其中是否有任何可见。自动完成下拉窗口类名称为Auto-Suggest Dropdown
。您可以使用GetClassName
方法获取枚举窗口的类名,然后使用IsWindowVisible
方法检查窗口是否可见。
示例强>
在下面的示例中,我在问题的代码中使用了一个类似于你的计时器,并且在计时器的tick事件中,我检查了是否有一个自动完成的窗口打开我显示"开放"在表格的标题中,否则显示"关闭":
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
答案 1 :(得分:0)
Reza Aghaei的方法翻译成C#:
public delegate bool EnumThreadDelegate(IntPtr hwnd, IntPtr lParam);
[DllImport("kernel32.dll")]
public static extern uint GetCurrentThreadId();
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumThreadWindows(uint dwThreadId, EnumThreadDelegate lpfn, IntPtr lParam);
bool isAutoCompleteListOpen = false;
EnumThreadDelegate callback = (IntPtr hwnd, IntPtr lParam) =>
{
var cn = new StringBuilder("", 256);
GetClassName(hwnd, cn, 256);
if (cn.ToString() == "Auto-Suggest Dropdown" && IsWindowVisible(hwnd)) {
isAutoCompleteListOpen = true;
return false;
}
return true;
};
EnumThreadWindows(GetCurrentThreadId(), callback, IntPtr.Zero);
return isAutoCompleteListOpen;
为获得更好的性能,这里我们在找到打开列表后在回调中返回false
,这将停止枚举。