1

I am currently working on a project of mine, i call it "Automated speech detector" Basically this program sits in the system tray most of the time just listening for user input.

I have now come to a conclusion that i will not be able to fill the "command" array with all the commands people want so i have decided i want tointegrate a "AddCommand" user input. Where the user can input a desired command themself and the program will later do whatever i decide it to do. However i really need help with this.

How can i make a string array method that takes 1 argument, the argument will be the userinputs string "command". adding that userinput to the string array. Is this possible? this is my current given code for the "default" commands i have set.

            Choices commands = new Choices();
            commands.Add(new string[] { "dollar", "euro", "hotmail", "notepad", "outlook", "onedrive", "discord" });
            GrammarBuilder gBuilder = new GrammarBuilder();
            gBuilder.Append(commands);
            Grammar grammar = new Grammar(gBuilder);

So it will work something like this only that the other array like commands2 will be able to take 1 argument and insert that to the array. Code below is the whole project if neccesary to look at.

public partial class Form1 : Form
{
    public SpeechRecognitionEngine recEngine; 
    public static bool keyHold = false;

    NotifyIcon IconPicture;
    Icon ActiveIcon;

    public Form1()
    {
        InitializeComponent();

    }

    private void Form1_Load(object sender, EventArgs e)
    {
        #region Icon and windows system tray dropdown text & click events
        //Creating icon and setting it to default.
        ActiveIcon = new Icon("speak_lzW_icon.ico");
        IconPicture = new NotifyIcon();
        IconPicture.Icon = ActiveIcon;
        //iconPicture.Visible = true;

        //Creating menu item for window in system tray.
        //MenuItem ProgNameMenuItem = new MenuItem("Voice detection by: Lmannen");
        MenuItem QuitMenuItem = new MenuItem("Quit");           
        ContextMenu contextMenu = new ContextMenu();
        contextMenu.MenuItems.Add(ProgNameMenuItem);
        contextMenu.MenuItems.Add(QuitMenuItem);

        //Adding the icon to the system tray window.
        IconPicture.ContextMenu = contextMenu;

        //System tray click event handlers
        QuitMenuItem.Click += QuitMenuItem_Click;
        IconPicture.MouseDoubleClick += IconPicture_MouseDoubleClick1;
        #endregion

        #region SpeechRecognition commands & event handlers
        recEngine = new SpeechRecognitionEngine();
        recEngine.SpeechRecognized += new EventHandler<SpeechRecognizedEventArgs>(recEngine_SpeechRecognized);
        recEngine.AudioStateChanged += new EventHandler<AudioStateChangedEventArgs>(recEngine_AudioStateChange);

        Choices commands = new Choices();
        commands.Add(new string[] { "dollar", "euro", "hotmail", "notepad", "outlook", "onedrive", "discord" });
        GrammarBuilder gBuilder = new GrammarBuilder();
        gBuilder.Append(commands);
        Grammar grammar = new Grammar(gBuilder);

        recEngine.SetInputToDefaultAudioDevice();
        recEngine.LoadGrammarAsync(grammar);
        recEngine.RequestRecognizerUpdate();
        recEngine.RecognizeAsync(RecognizeMode.Multiple);
        #endregion          
    }

    internal void recEngine_AudioStateChange(object sender, AudioStateChangedEventArgs e)
    {
        InputStatusLbl.Text = string.Format("{0}", e.AudioState);
    }

    internal static void recEngine_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
    {
        switch(e.Result.Text)
        {
            case "notepad":
                System.Diagnostics.Process.Start("notepad.exe");
                break;

            case "hotmail":
                System.Diagnostics.Process.Start("https://outlook.live.com/owa/");
                break;

            case "outlook":
                System.Diagnostics.Process.Start("https://outlook.live.com/owa/");
                break;

            case "ondrive":
                System.Diagnostics.Process.Start("https://onedrive.live.com/");
                break;

            case "discord":
                string name = Environment.UserName;
                string path = string.Format(@"C:\Users\{0}\AppData\Local\Discord\app-0.0.300\Discord.exe", name);
                System.Diagnostics.Process.Start(path);
                break;
        }
    }

    private void Form1_Resize(object sender, EventArgs e)
    {
        if(WindowState == FormWindowState.Minimized)
        {
            ShowInTaskbar = false;
            ShowIcon = false;
            IconPicture.Visible = true;

        }
    }

    private void IconPicture_MouseDoubleClick1(object sender, MouseEventArgs e)
    {
        ShowInTaskbar = true;
        IconPicture.Visible = false;
        ShowIcon = true;
        WindowState = FormWindowState.Normal;
    }

    private void QuitMenuItem_Click(object sender, EventArgs e)
    {
        IconPicture.Dispose();
        this.Close();
    }



    private void addToolStripMenuItem_Click(object sender, EventArgs e)
    {
        string input = Microsoft.VisualBasic.Interaction.InputBox("Add a voice-command by text", "Command");
        MessageBox.Show(input + " is now added to the command list");
    }
}

}

Ňɏssa Pøngjǣrdenlarp
  • 38,411
  • 12
  • 59
  • 178
wille480
  • 45
  • 8
  • 1
    Are you looking for [List](https://www.dotnetperls.com/list)? Your question is very confusing – maccettura Jan 16 '18 at 19:36
  • 1
    It's not really clear to me where you're stuck. You can create a method that takes any argument you want. You know how to "add" a `string[]` array to a `Choices` object already. I guess I just don't see what the actual question/problem is here. Have you tried something that hasn't worked in some specific way? – David Jan 16 '18 at 19:37
  • https://stackoverflow.com/questions/1836959/how-to-add-to-end-of-array-c –  Jan 16 '18 at 19:39
  • Hey, ye will i currently have my own "Choices command" object set. Now i want another command object "Choices command2" instead that can take a userinput instead, rathet than me adding every possible command i can come up with. Basicly through the "addtoolstripmenuitem_Click events" i want the users to be able to take the string input and insert it in a " Choices command2". Basicly i have 1 array for my own set default commands and then i have a second array where users can input their assired command. – wille480 Jan 16 '18 at 19:45

1 Answers1

0

Having some background on your task, I believe you need a Dictionary. It will be a public variable at the form level. The key will be the command and the value will be the path of execution. In the form, you'll initialize it with your 5 values BEFORE assigning your events.

Public Dictionary<String, String> Commands = new Dictionary<String, String>();

So in the form load (you'll need 5 of these):

Dictionary.Add("notepad", "notepad.exe");
Dictionary.Add("hotmail", "https://outlook.live.com/owa/");

Instead of a case statement, you will search the dictionary and if the key exists, you will start the value. Assuming you have a dictionary called commands it would be:

string command = "";
if ( Commands.TryGetValue(e.Result.Text, out command))
    System.Diagnostics.Process.Start(command)

The add command will path in the command name and the application path and add to the dictionary.

Commands.Add(commandName, pathToCommand);

Note that when you do this, you should ALSO save to a file in the users local application data area that can be brought back on form load, so its retained, but that's out of scope.

Ctznkane525
  • 7,297
  • 3
  • 16
  • 40
  • Hey, Thank you for your help so far : ) , I clearly understand where you are going with this and i think it is a great idea but i just dont know what to declare as the public variable. As far as the rest of the code i think i can manage! – wille480 Jan 17 '18 at 21:09
  • list of commands - Public Dictionary Commands = new Dictionary(); – Ctznkane525 Jan 17 '18 at 21:44
  • I did like this. Public partial class Form1 : Form { public static Dictionary CommandsList { get; set; } }. Then under form1_load i added this " CommandsList = new Dictionary(string, string>(); . Thats as long as i have come. I hope this is correct but i do not know how i am gonna handle this dictionary in the GrammarBuilder? here is the full code so you can see how it looks like. https://pastebin.com/tXPPCK8W – wille480 Jan 17 '18 at 22:00
  • Do i even need to use this anymore? Choices commands = new Choices(); commands.Add(commands); GrammarBuilder gBuilder = new GrammarBuilder(); gBuilder.Append(commands); Grammar grammar = new Grammar(gBuilder); – wille480 Jan 17 '18 at 22:03
  • Yes...because when you add a command it needs to go into your grammar as well – Ctznkane525 Jan 17 '18 at 22:13
  • Oki sir! How do i handle that? I did pass commands.add(CommandsList) but it gave error string can not convert dictionary or something like that. – wille480 Jan 17 '18 at 22:16
  • You need multiple lists...I guess the dictionary needs to be named something different...didn't realize you had a var named commands already – Ctznkane525 Jan 17 '18 at 22:21
  • I just dont see me handling this one very well "Public Dictionary Commands = new Dictionary();" . i cant put it in the public partial class form1:form , then it just gives error and i can either not put it in the form1_load cuz then it gives error with the public statement. and then i cant access it anywhere else in the form1_load code. So i dont really know what to do. – wille480 Jan 18 '18 at 16:06
  • it needs to be declared at a class level...inside the form1.vb file (not the designer)...above your first method call – Ctznkane525 Jan 18 '18 at 16:52
  • There is no way a dictionary can be loaded as grammar. I dont find anything of it. – wille480 Jan 24 '18 at 12:04
  • Your commands object above takes an array of strings...the dictionaries keys can easily be converted to an array of strings – Ctznkane525 Jan 24 '18 at 12:48
  • How do i do that? Have tried with alot. Like foreach(Keyvaluepair value in CommandsList, then i tried with for(int i = 0; i < CommandsList. Count; i++. I just dont find a way to pass on all the strings in the dictionary to an string[] where i can pass that in to the grammar – wille480 Jan 24 '18 at 12:52
  • assuming you have an import of system.linq at the top...you could do commands.Add(CommandsList.Keys.ToArray);...then do the other code to redefine the grammar – Ctznkane525 Jan 24 '18 at 12:57
  • Do you mean the foreach loop or the regular for loop ? – wille480 Jan 24 '18 at 16:50
  • commands.Add(CommandsList.Keys.ToArray) creates the array all in one shot...there's no need for a loop – Ctznkane525 Jan 24 '18 at 16:55
  • Okay nice! finally its working , the only thing that is not working properly now is that when i add a command through my click event, it will not load into the grammar builder as its not within that scope. Any therotical solutions for this? – wille480 Jan 24 '18 at 19:17
  • the grammar and related objects also must be public too...and you need a method to call the addition and move it out of the form load to somewhere you can call in both the form load and the button click event – Ctznkane525 Jan 24 '18 at 20:05