[Custom AutoComplete]

About

Sunday, April 27, 2003

The WinShell DLL from the Gregor.NET application framework lets .NET applications provide custom data sources for use with the Shell's auto-complete feature. This article shows an example of how to use it.

The Code

Create a class as an auto-complete source, and a form. In the form class, override the OnLoad method to execute code that hooks up your auto-complete source to a textbox control, using an auto completer object that is referenced by the form instance:

// file CustomAC.cs
using System;
using System.Collections.Specialized;
using System.Windows.Forms;
using Gregor.WinShell;

public class CTestAutoCompleteProvider : IAutoCompleteProvider {

    private StringCollection m_AllStrings;

    public CTestAutoCompleteProvider(){
        m_AllStrings = new StringCollection();
        m_AllStrings.Add("House\\Window");
        m_AllStrings.Add("House\\Door");
        m_AllStrings.Add("House\\Door\\Knob");
        m_AllStrings.Add("House\\Door\\Handle");
        m_AllStrings.Add("Prima\\Donna");
        m_AllStrings.Add("Prima\\Vera");
    }

    public string Name{
        get{
            return "TestAutoCompleteProvider";
        }
    }

    public StringCollection GetMatches(string sTyped){
        StringCollection list = new StringCollection();
        foreach(string s in m_AllStrings){
            if(sTyped != null && sTyped.Length > 0){
                // use strings at the appropriate level
                if(s.StartsWith(sTyped)){
                    list.Add(this.ExtractLength(s, s.IndexOf("\\", sTyped.Length)));
                }
            }else{
                // only use top-level strings
                list.Add(this.ExtractLength(s, s.IndexOf("\\")));
            }
        }
        return list;
    }

    private string ExtractLength(string s, int nLength){
        if(nLength == -1){
            return s;
        }else{
            return s.Substring(0, nLength);
        }
    }

}

public class Form1 : Form {

    private TextBox m_TextBox;
    private CAutoCompleter m_AutoCompleter;

    public Form1(){
        m_TextBox = new TextBox();
        this.Controls.Add(m_TextBox);
    }

    protected override void OnLoad(EventArgs e){
        try{
            IAutoCompleteProvider provider = new CTestAutoCompleteProvider();
            m_AutoCompleter = new CAutoCompleter(provider);
            m_AutoCompleter.Initialize(m_TextBox.Handle, AutoCompleteOptions.AutoAppend | AutoCompleteOptions.AutoSuggest);
        }catch(Exception ex){
            System.Diagnostics.Debug.WriteLine(ex);
        }
        base.OnLoad(e);
    }

    public static void Main(string[] args){
        Application.Run(new Form1());
    }

}

The Build

Compile the application this way (you'll need Core.dll and WinShell.dll from Gregor.NET):

csc /target:winexe /r:System.dll,System.Windows.Forms.dll,WinShell.dll,Core.dll CustomAC.cs

Notes

Your provider object can be retrieved from the CAutoCompleter instance if necessary. You may use one provider object for several text boxes. The auto completer can only service one text box, however.

To date, the Shell only recognizes the backslash (and supposedly the slash) as a separator. It would be interesting to use other tokens, such as the dot, as separators, but there is no way to do that.