SHAutoCompleteを使うと、テキスト入力部を持つコントロールにURLのオートコンプリート機能を付けることができる。 SHAutoCompleteにオートコンプリート機能を持たせたいコントロールのハンドルと動作を決めるフラグを渡すだけでオートコンプリート機能が有効になる。 ただし、ComboBoxの場合はこの方法ではうまく動作しないので、ここではComboBoxコントロールにURLのオートコンプリート機能を付ける方法を紹介する。

''' <summary>
''' オートコンプリート機能を持ったコンボボックス
''' </summary>
Public Class AutoCompleteComboBox

    Inherits System.Windows.Forms.ComboBox

    <DllImport("user32.dll")> _
    Private Shared Function FindWindowEx( _
        ByVal hWndParent As IntPtr, _
        ByVal hwndChildAfter As IntPtr, _
        ByVal lpszClass As String, _
        ByVal lpszWindow As String) _
        As IntPtr
    End Function

    <DllImport("shlwapi.dll")> _
    Private Shared Function SHAutoComplete( _
        ByVal hwndEdit As IntPtr, _
        ByVal dwFlags As SHAutoCompleteFlags) _
        As Integer
    End Function

    <Flags()> _
    Private Enum SHAutoCompleteFlags As Integer

        SHACF_DEFAULT = &H0
        SHACF_FILESYSTEM = &H1
        SHACF_URLALL = SHACF_URLHISTORY Or SHACF_URLMRU
        SHACF_URLHISTORY = &H2
        SHACF_URLMRU = &H4
        SHACF_USETAB = &H8
        SHACF_FILESYS_ONLY = &H10
        SHACF_AUTOSUGGEST_FORCE_ON = &H10000000
        SHACF_AUTOSUGGEST_FORCE_OFF = &H20000000
        SHACF_AUTOAPPEND_FORCE_ON = &H40000000
        SHACF_AUTOAPPEND_FORCE_OFF = &H80000000

    End Enum

    Protected Overrides Sub OnHandleCreated(ByVal e As EventArgs)

        Dim hWndEdit As IntPtr = FindWindowEx(Me.Handle, IntPtr.Zero, "EDIT", Nothing)

        ' オートコンプリートを有効にする
        If Not IntPtr.Zero.Equals(hWndEdit) Then SHAutoComplete(hWndEdit, SHAutoCompleteFlags.SHACF_URLALL)

        MyBase.OnHandleCreated(e)

    End Sub

End Class

このコードでは、OnHandleCreated()メソッドをオーバーライドし、ハンドルが作成された時点でSHAutoCompleteを呼び出している。 ここで、オートコンプリート機能を適用するためのウィンドウハンドルは直接ComboBox.Handleを使うのではなく、ComboBoxの中にある「EDIT」というクラス名を持つウィンドウハンドルを用いる。

なお、以前に直接入力したアドレスを取得するには、レジストリのHKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\TypedURLsに格納されている値を参照する。 ここにある「URL?」(?は10進の数字)という名前のキーを順に読んでいくことで以前に直接入力したアドレスを取得できる。

Dim keyUrls As Microsoft.Win32.RegistryKey

keyUrls = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("Software\Microsoft\Internet Explorer\TypedURLs")

Dim urlCount As Integer = 1

comboBox.BeginUpdate()

Do

    Dim url As String = CStr(keyUrls.GetValue(String.Format("url{0}", urlCount), String.Empty))

    If String.Empty.Equals(url) Then Exit Do

    comboBox.Items.Add(url)

    urlCount += 1

Loop

comboBox.EndUpdate()