【问题标题】:Windows Forms - Open suggestions list programatically after setting the autocomplete sourceWindows 窗体 - 设置自动完成源后以编程方式打开建议列表
【发布时间】:2014-09-03 08:58:39
【问题描述】:

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

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

【问题讨论】:

    标签: winforms autocomplete


    【解决方案1】:

    您的选择是:

    1. 使用 hacky 解决方案
    2. 使用纯 C# 自动完成控件(例如,自己编写或使用其他人的)
    3. 切换到组合框

    您可以自己找到#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

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

    【讨论】:

    • 哇。对于这样一个简单的用例来说,看起来很 hacky。会试试的。
    • 我很确定 PostMessage 可以正常工作,但似乎我在代码中更改了一些内容,但现在无法正常工作。无论如何,如果它不起作用,你可以做control.Focus(); SendKeys.Send(" ");
    • 似乎是一个小的延迟,然后是 Show() 可以解决问题。使用PostMessage 添加了适合我的代码。
    猜你喜欢
    • 2013-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-02
    • 2015-11-27
    • 1970-01-01
    • 2021-03-17
    • 1970-01-01
    相关资源
    最近更新 更多