See the question and my original answer on StackOverflow

Here is a piece of reusable code that may get you started, here is how you use it with a standard Windows Forms application that has a standard Textbox on it:

public partial class Form1 : Form
{
    private AutoCompletion _ac;

    public Form1()
    {
        InitializeComponent();

        // add the autocompletion tool to the 'textBox1' text box 
        _ac = new AutoCompletion(textBox1);
        _ac.TextChanged += AutoCompletionTextChanged;
    }

    private void AutoCompletionTextChanged(object sender, EventArgs e)
    {
        if (ShowSomething())
        {
            // clear the items and add 50 as an example
            _ac.Items.Clear();
            for (int i = 0; i < 50; i++)
            {
                AutoCompletion.AutoCompletionItem item = new AutoCompletion.AutoCompletionItem();
                item.Text = "Item " + i;
                _ac.Items.Add(item);
            }
            _ac.SelectedItem = _ac.Items[0]; // pre-select first one as an example
            _ac.Show(); // show the autocompletion window
            return;
        }
    }

    private bool ShowSomething()
    {
        return true; // TODO: implement this
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }

        base.Dispose(disposing);

        // don't forget to dispose the tool
        if (_ac != null)
        {
            _ac.Dispose();
        }
    }
}

And here is the code:

public sealed class AutoCompletion: IDisposable
{
    private AutoCompleteForm _form;
    private AutoCompletionItem _selectedItem;
    private readonly List<AutoCompletionItem> _items = new List<AutoCompletionItem>();

    public event EventHandler TextChanged;

    public AutoCompletion(TextBoxBase textBox)
    {
        if (textBox == null)
            throw new ArgumentNullException("textBox");

        _form = new AutoCompleteForm(this);
        _form.SetOwner(textBox);
        Margin = new Padding(2, 0, 30, 0);
        ImageMargin = 2;
        BorderStyle = FormBorderStyle.SizableToolWindow;
        MinimumLines = 1;
        MaximumLines = 100;
        IsEnabled = true;
    }

    public bool IsEnabled
    {
        get
        {
            return _form.IsEnabled;
        }
        set
        {
            _form.IsEnabled = value;
        }
    }

    public bool UserDismissed
    {
        get
        {
            return _form.UserDismissed;
        }
        set
        {
            _form.UserDismissed = value;
        }
    }

    public AutoCompletionItem SelectedItem
    {
        get
        {
            return _selectedItem;
        }
        set
        {
            if (_selectedItem == value)
                return;

            _selectedItem = value;
        }
    }

    public Font Font
    {
        get
        {
            return _form.ListBoxFont;
        }
        set
        {
            _form.ListBoxFont = value;
        }
    }

    public int MinimumLines
    {
        get
        {
            return _form.MinimumLines;
        }
        set
        {
            _form.MinimumLines = value;
        }
    }

    public int MaximumLines
    {
        get
        {
            return _form.MaximumLines;
        }
        set
        {
            _form.MaximumLines = value;
        }
    }

    public int ImageMargin
    {
        get
        {
            return _form.ImageMargin;
        }
        set
        {
            _form.ImageMargin = value;
        }
    }

    public Padding Margin
    {
        get
        {
            return _form.ListBoxMargin;
        }
        set
        {
            _form.ListBoxMargin = value;
        }
    }

    public FormBorderStyle BorderStyle
    {
        get
        {
            return _form.FormBorderStyle;
        }
        set
        {
            _form.FormBorderStyle = value;
        }
    }

    public ImageList Images
    {
        get
        {
            return _form.Images;
        }
        set
        {
            _form.Images = value;
        }
    }

    public IList<AutoCompletionItem> Items
    {
        get
        {
            return _items;
        }
    }

    public void Hide()
    {
        _form.HideList();
    }

    public void Show()
    {
        _form.ShowList();
    }

    public void Dispose()
    {
        if (_form != null)
        {
            _form.Dispose();
            _form = null;
        }
    }

    private void OnTextChanged(object sender, EventArgs e)
    {
        EventHandler handler = TextChanged;
        if (handler != null)
        {
            handler(sender, e);
        }
    }

    public class AutoCompletionItem
    {
        public AutoCompletionItem()
            : this(null)
        {
        }

        public AutoCompletionItem(string text)
            : this(text, -1)
        {
        }

        public AutoCompletionItem(string text, int imageIndex)
            :this(text, null, imageIndex)
        {
        }

        public AutoCompletionItem(string text, string toolTip, int imageIndex)
            :this(text, toolTip, null, imageIndex)
        {
        }

        public AutoCompletionItem(string text, string toolTip, string toolTipTitle, int imageIndex)
        {
            if (text == null)
            {
                text = string.Empty;
            }
            Text = text;
            ToolTip = toolTip;
            ImageIndex = imageIndex;
            ToolTipTitle = toolTipTitle;
        }

        public string Text { get; set; }
        public string ToolTip { get; set; }
        public string ToolTipTitle { get; set; }
        public int ImageIndex { get; set; }
    }

    private class AutoCompleteForm : Form
    {
        private readonly ImageListBox _listBox;
        private TextBoxBase _textBox;
        private bool _isEnabled;
        private readonly AutoCompletion _autoCompletion;

        [DllImport("user32.dll")]
        private static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);

        [DllImport("user32.dll")]
        private static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong);

        [DllImport("user32.dll")]
        private static extern int MsgWaitForMultipleObjectsEx(int nCount, IntPtr pHandles, int dwMilliseconds, int dwWakeMask, int dwFlags);

        [StructLayout(LayoutKind.Sequential)]
        private struct RECT
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
        }

        private const int GWL_HWNDPARENT = -8;
        private const int WM_KEYDOWN = 0x0100;
        private const int WM_KEYUP = 0x0101;
        private const int WM_SIZING = 0x0214;
        private const int WM_NCHITTEST = 0x0084;
        private const int HTNOWHERE = 0;
        private const int HTLEFT = 10;
        private const int HTTOP = 12;
        private const int HTTOPLEFT = 13;
        private const int HTTOPRIGHT = 14;
        private const int HTBOTTOMLEFT = 16;
        private const int MWMO_INPUTAVAILABLE = 0x0004;

        private class ImageListBox : ListBox
        {
            private ImageList _images;
            private int _imageMargin;
            private readonly AutoCompleteForm _form;
            public readonly ToolTip _toolTip;
            private Point _lastToolTipPoint;

            public ImageListBox(AutoCompleteForm form)
            {
                _form = form;
                BorderStyle = BorderStyle.None;
                SelectionMode = SelectionMode.One;
                DisplayMember = "Text";
                Dock = DockStyle.Fill;
                DrawMode = DrawMode.OwnerDrawFixed;
                _toolTip = new ToolTip();
            }

            protected override void OnSelectedIndexChanged(EventArgs e)
            {
                base.OnSelectedIndexChanged(e);
                if (SelectedIndices.Count == 0)
                    return;

                Rectangle rect = GetItemRectangle(SelectedIndices[0]);
                AutoCompletionItem item = (AutoCompletionItem)Items[SelectedIndices[0]];
                _toolTip.Show(item.ToolTip, this, Width + 2 * _form.BorderSize.Width, rect.Top);
                if (!string.IsNullOrEmpty(item.ToolTipTitle))
                {
                    _toolTip.ToolTipTitle = item.ToolTipTitle;
                }
                _toolTip.ShowAlways = true;
            }

            protected override void OnDoubleClick(EventArgs e)
            {
                _form.Commit(null);
            }

            protected override void OnMouseMove(MouseEventArgs e)
            {
                base.OnMouseMove(e);
                int index = IndexFromPoint(e.Location);
                if ((index >= 0) && (index < Items.Count))
                {
                    AutoCompletionItem item = (AutoCompletionItem)Items[index];
                    if (!string.IsNullOrEmpty(item.ToolTip))
                    {
                        // avoid flickering
                        if ((_toolTip.GetToolTip(this) != item.ToolTip) && (_lastToolTipPoint != e.Location))
                        {
                            _toolTip.SetToolTip(this, item.ToolTip);
                            if (!string.IsNullOrEmpty(item.ToolTipTitle))
                            {
                                _toolTip.ToolTipTitle = item.ToolTipTitle;
                            }
                            _lastToolTipPoint = e.Location;
                        }
                    }
                }
            }

            protected override void WndProc(ref Message m)
            {
                // we need this to track the TAB character
                if ((m.Msg == WM_KEYUP) && (m.WParam.ToInt32() == 9))
                {
                    _form.OnTabPressed();
                    m.Result = new IntPtr(1); // handled
                    return;
                }
                base.WndProc(ref m);
            }

            public int ImageMargin
            {
                get
                {
                    return _imageMargin;
                }
                set
                {
                    if (_imageMargin == value)
                        return;

                    _imageMargin = value;
                    Invalidate();
                }
            }

            public ImageList Images
            {
                get
                {
                    return _images;
                }
                set
                {
                    if (_images == value)
                        return;

                    _images = value;
                    if (_images != null)
                    {
                        ItemHeight = _images.ImageSize.Height + Margin.Vertical;
                    }
                    Invalidate();
                }
            }

            protected override void OnDrawItem(DrawItemEventArgs e)
            {
                if (e.Index < 0)
                    return;

                AutoCompletionItem item = (AutoCompletionItem)Items[e.Index];
                if (_images == null)
                {
                    e.DrawBackground();
                    e.DrawFocusRectangle();
                    using (Brush foreBrush = new SolidBrush(e.ForeColor))
                    {
                        e.Graphics.DrawString(item.Text, e.Font, foreBrush, e.Bounds);
                    }
                    return;
                }

                Rectangle bounds = e.Bounds;

                bounds.X += Margin.Left;
                if (item.ImageIndex >= 0)
                {
                    _images.Draw(e.Graphics, bounds.Left, bounds.Top, item.ImageIndex);
                    bounds.X += _images.ImageSize.Width + _imageMargin;
                }

                using (Brush backBrush = new SolidBrush(e.BackColor))
                {
                    e.Graphics.FillRectangle(backBrush, bounds);
                }

                if (((e.State & DrawItemState.Focus) == DrawItemState.Focus) && ((e.State & DrawItemState.NoFocusRect) != DrawItemState.NoFocusRect))
                {
                    ControlPaint.DrawFocusRectangle(e.Graphics, bounds, ForeColor, BackColor);
                }

                bounds.Y += Margin.Top;
                using (Brush foreBrush = new SolidBrush(e.ForeColor))
                {
                    e.Graphics.DrawString(item.Text, e.Font, foreBrush, bounds);
                }
            }
        }

        public AutoCompleteForm(AutoCompletion autoCompletion)
        {
            _autoCompletion = autoCompletion;
            ShowInTaskbar = false;
            ControlBox = false;
            MinimizeBox = false;
            MaximizeBox = false;
            Text = string.Empty;
            AutoScaleMode = AutoScaleMode.None;
            _listBox = new ImageListBox(this);
            _listBox.KeyDown += OnListBoxKeyDown;
            Controls.Add(_listBox);
            DockPadding.All = 0;
        }

        public bool UserDismissed { get; set; }
        public int MaximumLines { get; set; }
        public int MinimumLines { get; set; }

        public bool IsEnabled
        {
            get
            {
                return _isEnabled;
            }
            set
            {
                if (_isEnabled != value)
                {
                    _isEnabled = value;
                    if (!_isEnabled)
                    {
                        HideList();
                    }
                }
            }
        }

        public Font ListBoxFont
        {
            get
            {
                return _listBox.Font;
            }
            set
            {
                _listBox.Font = value;
            }
        }

        public Padding ListBoxMargin
        {
            get
            {
                return _listBox.Margin;
            }
            set
            {
                _listBox.Margin = value;
            }
        }

        public int ImageMargin
        {
            get
            {
                return _listBox.ImageMargin;
            }
            set
            {
                _listBox.ImageMargin = value;
            }
        }

        public ImageList Images
        {
            get
            {
                return _listBox.Images;
            }
            set
            {
                _listBox.Images = value;
            }
        }

        private Size BorderSize
        {
            get
            {
                Size size = Size - ClientSize;
                return new Size(size.Width / 2, size.Height / 2);
            }
        }

        private void OnTabPressed()
        {
            Commit(null);
        }

        private static bool PassThru(KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Up || e.KeyCode == Keys.Down || e.KeyCode == Keys.PageUp || e.KeyCode == Keys.PageDown)
                return false;

            return true;
        }

        private void OnListBoxKeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.Escape:
                    UserDismissed = true;
                    HideList();
                    return;

                case Keys.Return:
                    Commit(null);
                    return;

                case Keys.OemPeriod:
                case Keys.Decimal:
                    UserDismissed = false;
                    if (_listBox.SelectedItem == null)
                    {
                        // repost
                        PostMessage(_autoCompletion._form._textBox.Handle, WM_KEYDOWN, new IntPtr((int)e.KeyData), IntPtr.Zero);
                        return;
                    }
                    Commit(".");
                    return;

                default:
                    if (e.KeyCode == Keys.Back)
                    {
                        CaptureOriginalText();
                    }

                    if (PassThru(e))
                    {
                        PostMessage(_autoCompletion._form._textBox.Handle, WM_KEYDOWN, new IntPtr((int)e.KeyData), IntPtr.Zero);
                    }
                    return;
            }
        }

        private static Point GetSelectionPoint(TextBoxBase textBox)
        {
            using (Graphics graphics = Graphics.FromHwnd(textBox.Handle))
            {
                string text;
                if (textBox.Text.Length == 0)
                {
                    // use dummy text
                    text = "I";
                }
                else
                {
                    text = textBox.Text.Substring(0, textBox.SelectionStart);
                }
                SizeF size = graphics.MeasureString(text, textBox.Font);
                if (size.Width > textBox.Width)
                {
                    size.Width = textBox.Width;
                }
                return textBox.Parent.PointToScreen(new Point((int)(size.Width + textBox.Location.X), (int)(size.Height + textBox.Location.Y)));
            }
        }

        private bool _raiseTextChanged = true;
        private void Commit(string extra)
        {
            UserDismissed = false;
            if (_listBox.SelectedItem == null)
                return;

            _raiseTextChanged = false;

            string newSelection = ((AutoCompletionItem)_listBox.SelectedItem).Text + extra;

            string textBefore;
            if (_originalSelectionStart > 0)
            {
                textBefore = _originalText.Substring(0, _originalSelectionStart);
                int pos = textBefore.LastIndexOf('.');
                if (pos >= 0)
                {
                    textBefore = textBefore.Substring(0, pos);
                }
                else
                {
                    textBefore = string.Empty;
                }
            }
            else
            {
                textBefore = string.Empty;
            }

            if ((!textBefore.EndsWith(".")) && (!newSelection.EndsWith(".")) && (textBefore.Length > 0))
            {
                textBefore += ".";
            }

            _textBox.Text = textBefore + newSelection;// +textAfter;
            _textBox.SelectionLength = 0;
            _textBox.SelectionStart = _textBox.Text.Length;

            _raiseTextChanged = true;
            CaptureOriginalText();
            HideList();
        }

        public void SetOwner(TextBoxBase textBox)
        {
            if (textBox == null)
                throw new ArgumentNullException("textBox");

            _textBox = textBox;
            _textBox.KeyDown += OnTextBoxKeyDown;
            _textBox.TextChanged += OnTextBoxTextChanged;
        }

        private void OnTextBoxTextChanged(object sender, EventArgs e)
        {
            if (!IsEnabled)
                return;

            if (!_raiseTextChanged)
                return;

            _autoCompletion.OnTextChanged(_textBox, e);
        }

        private void CaptureOriginalText()
        {
            _originalText = _textBox.Text;
            _originalSelectionStart = _textBox.SelectionStart;
            _originalSelectionLength = _textBox.SelectionLength;
        }

        private void OnTextBoxKeyDown(object sender, KeyEventArgs e)
        {
            if (!IsEnabled)
                return;

            if (Visible)
                return;

            CaptureOriginalText();
        }

        public void HideList()
        {
            Visible = false;
        }

        public void ShowList()
        {
            if (_autoCompletion.Items.Count == 0)
                return;

            if ((_textBox.Text.EndsWith(".")) && (!_originalText.EndsWith(".")))
            {
                _originalText += ".";
                _originalSelectionStart++;
            }

            Visible = false;
            _listBox.Items.Clear();
            float maxWidth = 0;
            int height = _autoCompletion.Items.Count * _listBox.ItemHeight;
            using (Graphics graphics = Graphics.FromHwnd(_listBox.Handle))
            {
                foreach (AutoCompletionItem item in _autoCompletion._items)
                {
                    int index = _listBox.Items.Add(item);
                    if (item == _autoCompletion.SelectedItem)
                    {
                        _listBox.SelectedIndex = index;
                    }

                    if (item.Text != null)
                    {
                        SizeF size = graphics.MeasureString(item.Text, _listBox.Font);
                        if (size.Width > maxWidth)
                        {
                            maxWidth = size.Width;  
                        }
                    }
                }
            }

            SetWindowLong(Handle, GWL_HWNDPARENT, _textBox.Handle);

            Point point = GetSelectionPoint(_textBox);
            Size borderSize = BorderSize;
            if (Images != null)
            {
                point.X -= Images.ImageSize.Width;
            }
            point.X -= borderSize.Width + ListBoxMargin.Left + ImageMargin;
            point.Y += 4; // TODO: can we be smarter?

            Location = point;
            int width = (int)maxWidth + ListBoxMargin.Right;

            int minLines = MinimumLines;
            if (minLines < 1)
            {
                minLines = 1;
            }

            int maxLines = MaximumLines;
            if (maxLines < minLines)
            {
                maxLines = minLines;
            }

            height = Math.Min(height, maxLines * _listBox.ItemHeight);
            ClientSize = new Size(width, height);
            MinimumSize = new Size(width, minLines * _listBox.ItemHeight) + borderSize;
            MaximumSize = new Size(width * 2, maxLines * _listBox.ItemHeight);

            Visible = true;
            _listBox.Focus();
            DoModalLoop();
        }

        private string _originalText;
        private int _originalSelectionStart;
        private int _originalSelectionLength;

        private void DoModalLoop()
        {
            while (Visible)
            {
                typeof(Application).InvokeMember("DoEventsModal", BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.InvokeMethod, null, null, null);
                MsgWaitForMultipleObjectsEx(0, IntPtr.Zero, 250, 0xff, MWMO_INPUTAVAILABLE);
            }
        }

        protected override void OnDeactivate(EventArgs e)
        {
            base.OnDeactivate(e);
            _listBox._toolTip.Hide(_listBox);
            HideList();
        }

        protected override void WndProc(ref Message m)
        {
            // prevent resize handle on top & left of window
            if (m.Msg == WM_NCHITTEST)
            {
                base.WndProc(ref m);
                int ht = m.Result.ToInt32();

                // if user hit left or top, pretend he didn't
                if ((ht == HTLEFT) || (ht == HTBOTTOMLEFT) || (ht == HTTOP) || (ht == HTTOPLEFT) || (ht == HTTOPRIGHT))
                {
                    m.Result = new IntPtr(HTNOWHERE);
                }
                return;
            }

            // ensure integral height and maximum size
            if (m.Msg == WM_SIZING)
            {
                RECT rect = (RECT)Marshal.PtrToStructure(m.LParam, typeof(RECT));
                int h = rect.Bottom - rect.Top;
                int newh = h;
                if ((h % _listBox.ItemHeight) != 0)
                {
                    newh = ((h + _listBox.ItemHeight) / _listBox.ItemHeight) * _listBox.ItemHeight;
                }

                if (newh > (_listBox.ItemHeight * _listBox.Items.Count))
                {
                    newh = _listBox.ItemHeight * (_listBox.Items.Count + 1);
                }

                rect.Bottom = rect.Top + newh;
                Marshal.StructureToPtr(rect, m.LParam, false);
                m.Result = new IntPtr(1); // handled
                return;
            }

            base.WndProc(ref m);
        }
    }
}

Note: this is an extract from this 100% free component utility: CodeFluent Runtime Client