2018-04-10 22:51:57

OK, so I'm experiencing a highly frustrating set of circumstances. I am making an app that will allow you to type text and have it spoken by SAPI. That part is already done and is a windows forms app. You have the text box for typing, a control to adjust the rate, a speak button, and a menu bar that's not fully functional yet, but I have got the Exit option working. The problem comes into play when I create a function to get all the voices you have installed, grab their names and add those to the combobox. The code is valid, that's not the issue, the issue is I can't call the damn function. Now, I'm very new to C# and visual studio, which sort of presents its own unique little problems, in that getting an app up and running is stupidly easy, its more of wiring stuff up than coding. I think so far I put like 3 lines of my own code into it.

Anyway, I'm not exactly sure what the issue here is. Perhaps its me putting the function in the wrong place, but it won't let me put it some places. Anyway, fuck sakes, if I put it where it is happy to reside, which is like outside the main class but inside the namespace, I can't call it. If I type its nae, Intellisense will not pick it up, which is usually a good indicator that you're doing something wrong. If I complete it manually, it doesn't work, saying something about thinking I"m trying to define a new function rather than call one, even though I add the semicolon after the parens. Also, there is only some places in the code where intellisense picks up void, so I put it where it will, because as I said, if Intellisense doesn't try to complete something you typed, its a good indication something is wrong.

So no matter where I try to call the function from, or no matter where I place the function, no matter whether I make it static or public, it wants to throw a fit.

I don't want to create a static class just to do something I'll do once per launch of the app.

I also tried removing the function from the form.cs and putting it in in main.cs and making it public, but I couldn't even call it from somewhere else in main.cs, so if I can't do that, there's no way I'm gonna be able to call it in form.cs

Pain is life and life is pain.

Thumbs up

2018-04-10 23:26:10

In this case you need to create a accessor for your main form so you can call it from a static or outside class.

So for example your name is called Form1

Create a variable above the constructor within the class.

internal static Form1 MyName {get;set;}

Now in the constructor add the following

public Form1()
MyName = this;

Now whenever you want to call something use

Also if you have issues with crossthreading, use the ignore cross thread function.
And put that in the constructor as well.

If you need help shoot me a email , perhaps i can voice assist you on this.


Homepage: http://xsense.venict.nl
Skype: xsense29

Thumbs up +1

2018-04-10 23:30:40

I'll try it, I'm still not really good with classes and stuff of that nature. I'm just cobbling it together with almost no knowledge. To be honest, I'm surprised I got this far.

Pain is life and life is pain.

Thumbs up

2018-04-10 23:31:54 (edited by Xsense 2018-04-11 00:26:03)


Above you can download the source code.
I made a quick example with one text box and one combo box.
instead of using a button to speak, just type something in the text box and press enter to make it speak.
you still need to add things you want to it but thats upto you.

Also i programmed it in visual studio 2013.


Homepage: http://xsense.venict.nl
Skype: xsense29

Thumbs up +1

2018-04-11 01:10:54

Ah, thanks. I'll check it out. Really, there is no need for this app, its just something to help me learn, which is why I'm doing it. There is no real purpose.

Pain is life and life is pain.

Thumbs up

2018-04-11 02:28:30

Well, I got it working, thanks for the help. I must admit to not really understanding why that does what it does.

These two lines I'm not sure about

        internal static System.Speech.Synthesis.SpeechSynthesizer SpeechEngine { get; set; }
Is that some sort of pseudo class or something?

            SpeechEngine = new System.Speech.Synthesis.SpeechSynthesizer();
Why is this being done, it looks like this was done above, I'm not clear on what's going on here.

I also left that part as you have written it, even though I reference System.Speech.Synthesis namespace in my using statements at the top, but since I'm not sure what exactly is going on here, I didn't want to mess it up by just referring to the class inside the namespace.

I took a slightly different approach to selecting the item in the combo box. I didn't need to write a keyboard handler as you've done as they just do that by default. Also there's a way you can bind the enter key to the form itself such that enter fires off a button same as if you click it or with screen readers, tab and space or enter on it. The hotkey exists in my app to press ALT P which is the same as clicking on the button.

I was nervous about putting stuff inside             InitializeComponent();

I didn't know what it did either. Honestly, I have no idea how I got this far. The only thing I can think of is a lot of this is just like wiring stuff up. If I had to code all of that stuff by hand, showing the form window rather than using the designer, etc., Yeah I wouldn't count on success.

Pain is life and life is pain.

Thumbs up

2018-04-11 02:42:28

Hello, no problem glad i could help.
To answer few of your questions.

The  internal static .... line
Is basically a variable, for example if i would add a text box using code.

internal static TextBox MyBox {get; set;}

Would be the same as adding it on the form but it would require a few more bits to make it show up on there.
So using the definition we can call the tts to make something happen like speak.

Its a bit confusing to explain but in short its a variable.
And in this case its a variable pointing to the system.speech reference.

For your next question.
Why do i call it twice?

The first one is inside the constructor.
Where initialize is located.
A constructor is basically the first thing that loads when you run the program.
So Initializecomponents would load all the text boxes buttons etc on your form.

So what i have added when the form is loading / initializing.
Is basically to get all the installed voices and add them to the combo box on the form.

The one in the bottom where i create another instance of it.
Is to make sure that the speech synth is not null.
When null it wont be able to do anything.
So in case it would be null we create a new instance for it.
This way it will be able to run the functions that you want.
In this case set the voice and speak.

If you need more advice or help.
Or you want to learn some more be sure to contact me.
I will try my best to give you a hand.


Homepage: http://xsense.venict.nl
Skype: xsense29

Thumbs up

2018-04-11 03:11:18

Ah OK. Well the app is about the most ugly thing I've ever seen. I have some vision, so I can attest to its ugliness. I made a few improvements to it though. It now has labels over each control so sighted people know what they do, though for screen reader users, this is set to report to them without needing a label. I made the speak button smaller, added the voices combobox, and a menu bar on top that has two entries. File and help, File only has Exit, which does work, though you can always close it with the X in the corner, or hit ALT F4. There is also Help, which nothing is set up there yet.

Pain is life and life is pain.

Thumbs up

2018-04-11 03:26:19

Also, the internal specifier simply means that access to the variable is limited to the assembly, which is a fancy name for the program or library.

"On two occasions I have been asked [by members of Parliament!]: 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out ?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question."    — Charles Babbage.

Thumbs up