0

So I am trying to create a smart crosshair controlled by win 10 voice recognition engine for a game. The form 1 is used to turn on and turn off voice recognition .If it hears my saying "slow", it will draw a line on another transparent overlaying form

 public partial class Form1 : Form
    {
        formoverlay overlayform = new formoverlay();
        SpeechRecognitionEngine dasSpeechEngine = new SpeechRecognitionEngine(); 
        public Form1()
        {

            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            dasSpeechEngine.RecognizeAsync(RecognizeMode.Multiple);
            btnDisable.Enabled = true;
        }

        private void Form1_Load(object sender, EventArgs e)//load event
        {
            Choices commands = new Choices();
            commands.Add(new string[] { "slow", "medium", "fast","ultra","x"});
            GrammarBuilder gbuilder = new GrammarBuilder();
            gbuilder.Append(commands);
            Grammar thegrammar = new Grammar(gbuilder);

            dasSpeechEngine.LoadGrammarAsync(thegrammar);
            dasSpeechEngine.SetInputToDefaultAudioDevice();
            dasSpeechEngine.SpeechRecognized += dasSpeechEngine_SpeechRecognized;
            overlayform.timestart = DateTime.Now.Second;
            //MessageBox.Show(overlayform.timestart.ToString());   



            //for (si=1,si)
        }
        private void dasSpeechEngine_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
        {

            switch (e.Result.Text)
            {
                case "slow":
                    if (ModifierKeys.HasFlag(Keys.Control))//prevent accidentally sight change
                    {
                        //clear current canvas
                        //draw all the lines that has true bool flag
                        //draw all the marks
                        overlayform.theclearform();

                        overlayform.paintHorline(15, slowAimSet.lineStartY,slowAimSet.lineEndY,1);
                        break;
                    }
                    break;
            }
        }
    }

On the overlay form, the code (not including the partial class declaration):

Graphics g;
Pen myPen = new Pen(Color.Green);
Pen smallPen = new Pen(Color.GreenYellow);
public formoverlay()
{
    InitializeComponent();
}
private void formoverlay_Load(object sender, EventArgs e)
{
    this.BackColor = Color.Wheat;
    this.TransparencyKey = Color.Wheat;
    this.TopMost = true;
    this.FormBorderStyle = FormBorderStyle.None;

    int initialStyle = GetWindowLong (this.Handle, -20);
    SetWindowLong(this.Handle, -20, initialStyle | 0x80000 | 0x20);
    //enable click through


    //get wows window size;
    GetWindowRect(handle, out rect);

    this.Size = new Size(rect.right - rect.left, rect.bottom - rect.top);
    this.Top = rect.top;
    this.Left = rect.left;
    smallPen.Width = 2.0f;



}

public void paintHorline(int theTgtSpd,int tStartY, int tEndY, int thisRngMarkerDir)
{

    int rngMarkerOffset = 10;
    //aimlineForSpeed[] thisAimLine = new aimlineForSpeed [4];
    //g.DrawLine(myPen, 500,500, 600, 600);
   g.DrawLine(myPen, 0,tStartY, 1920, tEndY);   
}

public void theclearform()//everytime user say, re-draw everything
{
    Invalidate();
}   

When I run the program, when I say "slow", there us an errorenter image description here saying system argument exception: {"Parameter is not valid."} It does not make any difference if I write constant values in my draw calls, for example, g.DrawRectangle(myPen, 100, 100, 200,200);

Apparently, the program calls "painthorline" function, but it does not draw correctly. If I create a new graphics in painthorline method, it won't cause this error, but it does not draw anything at all..

Where did I go wrong? Did I need to create a sperate event in order to get the drawline/drawrectangle call works?

wildbill16
  • 11
  • 4
  • And where are you creating this graphics object, Also 98% of this code is not relevant to this question – TheGeneral Nov 06 '18 at 02:30
  • Why don't you start a test project, were you work out how to draw on a form first, then if you have a problem, at least its a specific minimal example without all your business logic – TheGeneral Nov 06 '18 at 02:37
  • 1
    Sorry, it's all wrong :) You need to use the `Paint()` event of a Control (any class) to draw on it. You can't store the `Graphics` object. It's going to be an invalid object the moment you assign it. Your `Form` is not an overlay, is a phantom. The Speech part is OK. :) – Jimi Nov 06 '18 at 02:39
  • Hi there! Welcome to StackOverflow. Please note that images of exceptions are useless. You've better show us actual exception message and a stack trace (if it is relevant). – vasily.sib Nov 06 '18 at 02:52
  • @Jimi Hello, thanks for the message. The problem is solved and it evolves to an incorrect draw coordinate issue. Indeed I didn't figure out how event and paint system work at first. I spent some time read the document though.. – wildbill16 Nov 06 '18 at 23:37
  • You'll find tons of info on this matter both on the MSDN Docs related to the `Paint()` event of .Net Controls and, of course, on SO. If you have other drawing issues, post another question, showing the relevant code. Also, as a suggestion, don't use `SetWindowLong` to set class styles. Use [CreateParams](https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.createparams). Maybe using meaningful values (e.g., `internal const int WS_EX_TRANSPARENT = 0x00000020;`). – Jimi Nov 06 '18 at 23:45
  • To draw something that will be actually visible on a translucent/transparent surface, see an example [here](https://stackoverflow.com/questions/51396681/circle-with-text?answertab=active#tab-top). – Jimi Nov 06 '18 at 23:51
  • @jimi I am reading it. May take a while to digest all these things. But thanks for the example link and the suggestion. – wildbill16 Nov 07 '18 at 00:05

0 Answers0