Windows窗体 - 在设置自动完成源后以编程方式打开建议列表

时间:2014-08-29 20:15:29

标签: winforms autocomplete

我的Windows窗体中有一个文本框,我已经配置了自动完成功能。当用户从网络服务中输入时,我会动态地提出建议。这是由后台工作人员完成的。

设置自动完成源后,如何以编程方式打开该文本框的建议? (类似于我们为组合框提供的属性 - DroppeDown)

1 个答案:

答案 0 :(得分:1)

您的选择是:

  1. 使用hacky解决方案
  2. 使用纯C#自动完成控件(例如自己编写或使用其他人)
  3. 切换到组合框
  4. 您可以自己找到#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

    即使有了句柄,也没有与其拥有的编辑控件的直接或间接链接。在上面的超链接中,确定编辑控件的唯一方法是在第一次显示自动完成时进行侦听,然后检查每个控件以查看屏幕边框上的哪个控件包含它。