-2

In my Tic Tac Toe game I ask the players for their names and I ask them whether they want it to be saved. The next time they start the game I want the InputBox to display some sort of auto complete or IntelliSense to appear.

QUESTION :

How do I get auto complete or IntelliSense to appear on InputBox

Just for in case. I included :

using Microsoft.VisualBasic;

in my code.

Dilan V
  • 313
  • 1
  • 3
  • 13
  • Plenty of ways to get auto-completion, the TextBox and ComboBox classes support it well. InputBox, no, that's far too primitive. Just create your own form instead, it isn't rocket science. – Hans Passant Sep 05 '14 at 16:15
  • I have edited your title. Please see, "[Should questions include “tags” in their titles?](http://meta.stackexchange.com/questions/19190/)", where the consensus is "no, they should not". – John Saunders Sep 06 '14 at 05:50

2 Answers2

1

In order to use an "Intellisense" by which I'm guessing you mean "AutoComplete", you can simply set up a TextBox and assign its AutoComplete... properties. The ones you'll need in particular are:

  1. AutoCompleteCustomSource - Which is just a collection, so you can add your own list of Strings to use as a source. That way you wont have to worry about a DataSet or any kind of database access, if you don't want to go that way.
  2. AutoCompleteMode - Which tells the control what type of AutoComplete input box it should be.
  3. AutoCompleteSource - Which in your case, if you use #1 as the solution, you'd set this to CustomSource.

edit

As an example:

textBox1.AutoCompleteMode = AutoCompleteMode.Suggest;
textBox1.AutoCompleteSource = AutoCompleteSource.CustomSource;
AutoCompleteStringCollection items = new AutoCompleteStringCollection();
items.Add("Save");
items.Add("Don't Save");

textBox1.AutoCompleteCustomSource = items;

edit 2

As requested, here is how to read a text file line by line and use the data within as the custom source for your AutoComplete

string line = "";
AutoCompleteStringCollection items = new AutoCompleteStringCollection();

// Read the file and display it line by line.
System.IO.StreamReader file = new System.IO.StreamReader("YOURFILE.txt");
while((line = file.ReadLine()) != null)
{
    if(!String.IsNullOrEmpty(line))
    {
        items.Add(line);
    }
}

file.Close();

Hope this helps!

laminatefish
  • 5,197
  • 5
  • 38
  • 70
  • Thanks, can you please add code about how to use the text from a .txt in the AutoComplete of the textbox? – Dilan V Sep 06 '14 at 09:40
-1

It is possible, requires quite a bit of code. Probably better just to write your own control.

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace Namespace {

public static class InputBoxEx {

    [STAThread]
    static void Main() {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        Form f = new Form();
        Button b = new Button { Text = "Button" };
        f.Controls.Add(b);

        b.Click += delegate {
            String[] words = new[] { "apple", "banana", "carrot" };
            InputBoxEx.ShowInputBox("Prompt", "Title", "Default", -1, -1, words);
        };

        Application.Run(f);
    }

    private static IntPtr hHook = IntPtr.Zero;
    private const int WH_CALLWNDPROCRET = 12;
    private delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);
    private static HookProc hookProc = new HookProc(InputBoxHookProc);
    private static String[] autoCompleteWords = null;

    public static String ShowInputBox(String prompt, String title, String defaultResponse, int xPos = -1, int yPos = -1, String[] autoCompleteWords = null) {
        init(autoCompleteWords);
        return Microsoft.VisualBasic.Interaction.InputBox(prompt, title, defaultResponse, xPos, yPos);
    }

    private static void init(String[] autoCompleteWords) {
        if (hHook != IntPtr.Zero)
            throw new Exception("Cannot be called by multiple threads.");

        InputBoxEx.autoCompleteWords = autoCompleteWords;
        int processID = GetCurrentThreadId();
        hHook = SetWindowsHookEx(WH_CALLWNDPROCRET, hookProc, IntPtr.Zero, processID);
    }

    // returns true if a TextBox is found
    private static bool assignAutoCompleteWords(IntPtr main) {
        List<IntPtr> ptr = GetChildWindows(main);
        foreach (IntPtr p in ptr) {
            TextBox c = Control.FromHandle(p) as TextBox;
            if (c == null)
                continue;

            c.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
            c.AutoCompleteSource = AutoCompleteSource.CustomSource;
            c.AutoCompleteCustomSource.AddRange(autoCompleteWords);
            return true;
        }
        return false;
    }

    private enum CbtHookAction : int {
        HCBT_MOVESIZE = 0,
        HCBT_MINMAX = 1,
        HCBT_QS = 2,
        HCBT_CREATEWND = 3,
        HCBT_DESTROYWND = 4,
        HCBT_ACTIVATE = 5,
        HCBT_CLICKSKIPPED = 6,
        HCBT_KEYSKIPPED = 7,
        HCBT_SYSCOMMAND = 8,
        HCBT_SETFOCUS = 9
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct CWPRETSTRUCT {
        public IntPtr lResult;
        public IntPtr lParam;
        public IntPtr wParam;
        public uint message;
        public IntPtr hwnd;
    };

    private static IntPtr InputBoxHookProc(int nCode, IntPtr wParam, IntPtr lParam) {
        if (nCode < 0) {
            return CallNextHookEx(hHook, nCode, wParam, lParam);
        }

        CWPRETSTRUCT msg = (CWPRETSTRUCT) Marshal.PtrToStructure(lParam, typeof(CWPRETSTRUCT));
        IntPtr hook = hHook;

        if (msg.message == (int) CbtHookAction.HCBT_ACTIVATE) {
            bool unhook = false;
            try {
                unhook = assignAutoCompleteWords(msg.hwnd);
            } catch {
                unhook = true;
            }

            if (unhook) {
                UnhookWindowsHookEx(hHook);
                hHook = IntPtr.Zero;
            }
        }

        return CallNextHookEx(hook, nCode, wParam, lParam);
    }

    [DllImport("user32.dll")]
    private static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);

    [DllImport("user32.dll")]
    private static extern int UnhookWindowsHookEx(IntPtr idHook);

    [DllImport("user32.dll")]
    private static extern IntPtr CallNextHookEx(IntPtr idHook, int nCode, IntPtr wParam, IntPtr lParam);

    [DllImport("user32.dll")]
    private static extern bool EnumThreadWindows(int dwThreadId, EnumThreadDelegate lpfn, IntPtr lParam);
    private delegate bool EnumThreadDelegate(IntPtr hWnd, IntPtr lParam);

    [DllImport("kernel32.dll")]
    private static extern int GetCurrentThreadId();

    [DllImport("user32.Dll")]
    private static extern bool EnumChildWindows(IntPtr parentHandle, Win32Callback callback, IntPtr lParam);
    private delegate bool Win32Callback(IntPtr hwnd, IntPtr lParam);

    private static List<IntPtr> GetChildWindows(IntPtr parent) {
        List<IntPtr> result = new List<IntPtr>();
        GCHandle listHandle = GCHandle.Alloc(result);
        try {
            Win32Callback childProc = new Win32Callback(EnumWindow);
            EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle));
        } finally {
            if (listHandle.IsAllocated)
                listHandle.Free();
        }
        return result;
    }

    private static bool EnumWindow(IntPtr handle, IntPtr pointer) {
        GCHandle gch = GCHandle.FromIntPtr(pointer);
        List<IntPtr> list = gch.Target as List<IntPtr>;
        if (list == null)
            throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>");
        list.Add(handle);
        return true;
    }
}
}
Loathing
  • 5,109
  • 3
  • 24
  • 35
  • -1 What's wrong with doing this through .NET? Are you sure you need all that Win32 code? – John Saunders Sep 06 '14 at 05:53
  • If you know a way to get a reference to the `TextBox` on the VB `InputBox` control then by all means post your solution. Are you sure you should downvote if you don't know the answer to the questions you ask? – Loathing Sep 06 '14 at 06:03
  • Are you saying that [this answer](http://stackoverflow.com/a/25690129/76337) doesn't work? Because it sure looks a lot like what I learned about autocomplete on Windows Forms text boxes back in .NET 2.0. – John Saunders Sep 06 '14 at 06:10
  • The question is asking about setting autocomplete on a `VB InputBox` which is a modal dialog. The post by LokiSinclair would work if you wrote your own control, but doesn't work for the `VB InputBox` dialog. – Loathing Sep 06 '14 at 06:23
  • Sorry, I'Inot familiar with the `InputBox`, so my eyes read `TextBox` for `InputBox`. I'll upvote you, but [so] requires that you edit the answer before I can do that. – John Saunders Sep 06 '14 at 10:51