【发布时间】:2014-09-03 08:58:39
【问题描述】:
我的 Windows 窗体中有一个文本框,我为其配置了自动完成功能。当用户从网络服务中输入时,我会动态地提出建议。这是由后台工作人员完成的。
设置自动完成源后,如何以编程方式打开该文本框的建议? (类似于我们为组合框提供的属性 - DroppeDown)
【问题讨论】:
标签: winforms autocomplete
我的 Windows 窗体中有一个文本框,我为其配置了自动完成功能。当用户从网络服务中输入时,我会动态地提出建议。这是由后台工作人员完成的。
设置自动完成源后,如何以编程方式打开该文本框的建议? (类似于我们为组合框提供的属性 - DroppeDown)
【问题讨论】:
标签: winforms autocomplete
您的选择是:
您可以自己找到#2 和#3。我认为#2是最好的选择。但是,如果您想做 #1,请继续阅读:
不存在您所要求的干净解决方案。我对自动完成的理解是它是一个 COM 对象,可能最初是为 Internet Explorer 构建的(因为 Spy++ 窗口在其层次结构中具有“Internet Explorer”标题)。无论如何,自动完成功能从编辑控件挂钩到 WndProc 事件。它在收到 KEY_DOWN 等通知事件时填充并显示列表。
例如,假设您有一个自动完成功能,其中至少包含一个以字母“A”开头的单词。您可以通过向 TextBox 发送 POST 消息来强制显示自动完成功能:
//host.Text = "A"; // does not work
PostMessage(textbox.Handle, WM_KEYDOWN, VK_A, 0); // works (see SendKey method below)
[DllImport("user32.dll")]
static extern bool PostMessage(IntPtr hWnd, UInt32 Msg, int wParam, int lParam);
// only works once the Handle has been assigned
public void Show() {
ShowWindow(Handle, SW_SHOWNOACTIVATE);
}
// e.g. VK_A = 0x41, VK_SPACE = 20;
public void SendKey(int VK_KEY) {
PostMessage(Host.Handle, 0x100, VK_KEY, 0);
System.Threading.Tasks.Task.Run((Action) delegate {
Thread.Sleep(10); // small delay required
Host.BeginInvoke((Action) delegate {
Show();
});
});
}
据我所知,无法直接控制自动完成中的内容。但是,在另一个 stackoverflow 线程中(现在找不到),答案是在每个单词前面加上一个空格,以便它们都共享一个公共前缀,然后再修剪该值。
您也可以强制显示自动完成而不输入任何内容,但不幸的是它将为空。例如:
const int SW_SHOWNOACTIVATE = 4;
IntPtr p = ...; // handle to Autocomplete window
int width = 400;
int height = 200;
SetWindowPos(p, IntPtr.Zero, -5, 0, width, height, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
ShowWindow(p, SW_SHOWNOACTIVATE);
您可以在此处了解如何获取句柄参考:Combo box drop down width on suggest
即使有了句柄,也没有直接或间接链接到它拥有的编辑控件。在上面的超链接中,确定编辑控件的唯一方法是在第一次显示自动完成时进行监听,然后检查每个控件以查看哪个控件的屏幕边界框包含它。
【讨论】:
PostMessage 可以正常工作,但似乎我在代码中更改了一些内容,但现在无法正常工作。无论如何,如果它不起作用,你可以做control.Focus(); SendKeys.Send(" ");
Show() 可以解决问题。使用PostMessage 添加了适合我的代码。