none
C# Detect Multiple keypress

    Question

  • Hello!

     

    I am learning C# after tried Java.

    Ive tried to program a program that can detect keystrokes, however when i add onKeyDown on my form it work but only one key at a time. So ive tried to add my e.keycode detect to a timer and got error.

     

     private void key_Tick(object sender, System.EventArgs e, KeyEventArgs e)

     

    That wont work and the timer wont run becuase i have 2 Args. Im really lost and do not really understand :(

     

    Could you help me out?

     

    EDIT* i am doing a litle easy game which reqier to detext multiple arrow key 

    Thank you!


    If you don´t Believe in it, Then it Doesn´t Exist!
    • Edited by Simon PH3K Wednesday, January 12, 2011 2:47 PM EDDIT
    Wednesday, January 12, 2011 2:44 PM

Answers

  • What did I wrote previously? "You need to keep track of what's going on"

    Set some variables to true when your KeyDown event detects the keys are pressed. Set those variables to false when the KeyUp event detects the keys are being released.

    private boolean GoingRight, GoingUp, GoingLeft, GoingDown;
    
    private void Form1_KeyDown(object sender, KeyEventArgs e)
    {
       if (e.KeyCode == Keys.Right)
          GoingRight = true;
       if (e.KeyCode == Keys.Up)
          GoingUp = true;
    
       if(GoingRight)
       {
          pictureBox1.Location = new Point(pictureBox1.Location.X + 6, pictureBox1.Location.Y);
       }
    
       if(GoingUp)
       {
          pictureBox1.Location = new Point(pictureBox1.Location.X, pictureBox1.Location.Y -5);
       }
    }
    
    private void Form1_KeyUp(object sender, KeyDownEventArgs e)
    {
       if (e.KeyCode == Keys.Right)
          GoingRight = false;
       if (e.KeyCode == Keys.Up)
          GoingUp = false;
    }
    
    
    Wednesday, January 12, 2011 5:20 PM
  • Simon,

    Try this example on a new form with a textbox to see if it gives you the functionality you are looking for.  Also, please note that I converted this from VB some the programming style nuances are probably not correct.

    using System; using System.Windows.Forms;using System.Runtime.InteropServices;
    using System.Collections.Generic;
    
    namespace WindowsFormsApplication1
    {
      public partial class Form1 : Form
      {
        public Form1()
        {
          InitializeComponent();
          this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(Form1_FormClosing);
          tm.Tick += new System.EventHandler(DoSomethingWithKeyboardInput);
          this.Load += new System.EventHandler(Form1_Load);
          textBox1.KeyDown += new System.Windows.Forms.KeyEventHandler(textbox1_KeyDown);
          textBox1.KeyUp += new System.Windows.Forms.KeyEventHandler(textbox1_KeyDown);
        }
    
        private Timer tm = new Timer();
        private List<System.Windows.Forms.Keys> MovementKeys = new List<System.Windows.Forms.Keys>();
        private _MyInputKeys MyInputKeys = new _MyInputKeys();
    
        private struct _MyInputKeys
        {
          public bool Jump;
          public bool Left;
          public bool Right;
        }
    
        private void Form1_FormClosing(object sender, System.Windows.Forms.FormClosingEventArgs e)
        {
          tm.Stop();
        }
    
        public void DoSomethingWithKeyboardInput(object sender, EventArgs e)
        {
          textBox1.Text = (MyInputKeys.Left ? "(left)" : "") + 
            (MyInputKeys.Right ? "(right)" : "") + (MyInputKeys.Jump ? "(jump)" : "");
        }
    
        private void Form1_Load(object sender, System.EventArgs e)
        {
          //define keys used for movement
    
          MovementKeys.Add(Keys.Up); //Jump ?
          MovementKeys.Add(Keys.Left); //Left Arrow - Move Left
          MovementKeys.Add(Keys.Right); //Rigth Arrow - Move Right
          tm.Interval = 50;
          tm.Start();
        }
    
        private void textbox1_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
        {
          if (MovementKeys.IndexOf(e.KeyCode) != -1)
          {
            e.Handled = true;
            MyInputKeys.Jump = IsKeyDown(Keys.Up);
            MyInputKeys.Left = IsKeyDown(Keys.Left);
            MyInputKeys.Right = IsKeyDown(Keys.Right);
          }
        }
    
        public static bool IsKeyDown(Keys key)
        {
          return (GetKeyState(Convert.ToInt16(key)) & 0X80) == 0X80;
        }
        /// <summary>
        ///  If the high-order bit is 1, the key is down; otherwise, it is up.
        ///  If the low-order bit is 1, the key is toggled. 
        ///  A key, such as the CAPS LOCK key, is toggled if it is turned on. 
        ///  The key is off and untoggled if the low-order bit is 0. 
        ///  A toggle key's indicator light (if any) on the keyboard will be on when 
        ///  the key is toggled, and off when the key is untoggled.
        /// </summary>
        /// <param name="nVirtKey"></param>
        [DllImport("user32.dll")]
        public extern static Int16 GetKeyState(Int16 nVirtKey);
      }
    }
    
    

    Wednesday, January 12, 2011 5:36 PM

All replies

  • I'm not sure if this is sensable... but just my understanding...

    The common keys that could be detected with multiple keys pressed in combination with other keys are: Shift, Ctrl, Alt

    Other than that... might have to create a separate thread or background worker to detect the non-multiple combinations (alpha, numeric, symbols, etc) with a time laps parameter between the multiple keys pressed.

    I might be wrong with my knowledge... i had put this in my alert just incase someone is able to accomplish this without background worker.

    Wednesday, January 12, 2011 3:02 PM
  • ive tried timer but i cant use both: object sender, System.EventArgs e, KeyEventArgs e)  

    (i cannot use to ARGS)

     

    When i try to walk my character with the arrow keys (onKeyDown Event)the character stop if i try to both run left and jump (2d graphic)


    If you don´t Believe in it, Then it Doesn´t Exist!
    Wednesday, January 12, 2011 3:14 PM
  • Use my answer in your VB thread.
    Wednesday, January 12, 2011 3:55 PM
  • Simon,

    You originally posted your question in the VB forum and it appears you got chased out before looking at the proposed solutions.  This method will allow you to detect the "down" status of any key irrespective if other keys are also pressed.

     

    using System; using System.Windows.Forms;using System.Runtime.InteropServices;
    
    namespace WindowsFormsApplication1
    {
      public partial class Form1 : Form
      {
        public Form1()
        {
          InitializeComponent();
          this.PreviewKeyDown += new System.Windows.Forms.PreviewKeyDownEventHandler(Form1_PreviewKeyDown);
    
        }
        private void Form1_PreviewKeyDown(object sender, System.Windows.Forms.PreviewKeyDownEventArgs e)
        {
          if (IsKeyDown(Keys.A) && IsKeyDown(Keys.Z))
          {
            MessageBox.Show("A and Z pressed at same time");
          }
        }
        public static bool IsKeyDown(Keys key)
        {
          return (GetKeyState(Convert.ToInt16(key)) & 0X80) == 0X80;
        }
        /// <summary>
        ///  If the high-order bit is 1, the key is down; otherwise, it is up.
        ///  If the low-order bit is 1, the key is toggled. 
        ///  A key, such as the CAPS LOCK key, is toggled if it is turned on. 
        ///  The key is off and untoggled if the low-order bit is 0. 
        ///  A toggle key's indicator light (if any) on the keyboard will be on when 
        ///  the key is toggled, and off when the key is untoggled.
        /// </summary>
        /// <param name="nVirtKey"></param>
        [DllImport("user32.dll")]
        public extern static Int16 GetKeyState(Int16 nVirtKey);
      }
    }
    

    Wednesday, January 12, 2011 3:57 PM
  • I accendently picked the wrong forum there. if you saw my title it was c#. Sorry.
    If you don´t Believe in it, Then it Doesn´t Exist!
    Wednesday, January 12, 2011 4:13 PM
  • Thank you. However what i meant was more like for example Super Mario. You can run right and at the same time jump. Because onKeyDown wont detect that.

     

    Thank you!


    If you don´t Believe in it, Then it Doesn´t Exist!
    Wednesday, January 12, 2011 4:15 PM
  • OnKeyDown will detect that. You need to keep track of what's going on.

    Here is what you get when you press right, then up, then release them (for this example, I suppose you release up, then right):

    > You press the Right arrow
    - you get OnKeyDown for the Right arrow
    * At this point, you know the Right arrow is pressed

    > You press the Up arrow
    - you get OnKeyDown for the Up arrow
    * At this point, you know the Right arrow and the Up arrow are pressed simultaneously

    > You release the Up arrow
    - you get OnKeyUp for the Up arrow
    * At this point, you know the Right arrow is the only pressed key

    > You release the Right arrow
    - you get OnKeyUp for the Right arrow
    * At this point, you know no keys are pressed

    Wednesday, January 12, 2011 4:32 PM
  • No...i dont think so. When i run right i keep holding right arrow. Then if i want to jump i still hold down the right arrow and then press the up key. What happends? the character stops :(
    If you don´t Believe in it, Then it Doesn´t Exist!
    Wednesday, January 12, 2011 4:39 PM
  • No...i dont think so. When i run right i keep holding right arrow. Then if i want to jump i still hold down the right arrow and then press the up key. What happends? the character stops :(
    Post your code showing how you are detecting multiple keypresses.  Perhaps you should try Louis's suggested solution.
    Wednesday, January 12, 2011 4:45 PM
  • No...i dont think so. When i run right i keep holding right arrow. Then if i want to jump i still hold down the right arrow and then press the up key. What happends? the character stops :(
    Post your code showing how you are detecting multiple keypresses.  Perhaps you should try Louis's suggested solution.

    No i am not detecting multiple keys that is the problem, here is the code:

    private void Form1_PreviewKeyDown(object sender, System.Windows.Forms.PreviewKeyDownEventArgs e)
        {
    
          if (e.KeyCode == Keys.Right)
          {
            
            
            pictureBox1.Location = new Point(pictureBox1.Location.X + 6, pictureBox1.Location.Y);
            // pictureBox1.Image = Properties.Resources._1R;
            );
            
          }
          
     if (e.KeyCode == Keys.Up)
          {
            pictureBox1.Location = new Point(pictureBox1.Location.X, pictureBox1.Location.Y -5);
                  }
    }
    
    And yes i know the picture/character will fly if i hold key up. However i cannot make it move up right. The character/picture stops if i press both.


    If you don´t Believe in it, Then it Doesn´t Exist!
    Wednesday, January 12, 2011 5:03 PM
  • What did I wrote previously? "You need to keep track of what's going on"

    Set some variables to true when your KeyDown event detects the keys are pressed. Set those variables to false when the KeyUp event detects the keys are being released.

    private boolean GoingRight, GoingUp, GoingLeft, GoingDown;
    
    private void Form1_KeyDown(object sender, KeyEventArgs e)
    {
       if (e.KeyCode == Keys.Right)
          GoingRight = true;
       if (e.KeyCode == Keys.Up)
          GoingUp = true;
    
       if(GoingRight)
       {
          pictureBox1.Location = new Point(pictureBox1.Location.X + 6, pictureBox1.Location.Y);
       }
    
       if(GoingUp)
       {
          pictureBox1.Location = new Point(pictureBox1.Location.X, pictureBox1.Location.Y -5);
       }
    }
    
    private void Form1_KeyUp(object sender, KeyDownEventArgs e)
    {
       if (e.KeyCode == Keys.Right)
          GoingRight = false;
       if (e.KeyCode == Keys.Up)
          GoingUp = false;
    }
    
    
    Wednesday, January 12, 2011 5:20 PM
  • Simon,

    Try this example on a new form with a textbox to see if it gives you the functionality you are looking for.  Also, please note that I converted this from VB some the programming style nuances are probably not correct.

    using System; using System.Windows.Forms;using System.Runtime.InteropServices;
    using System.Collections.Generic;
    
    namespace WindowsFormsApplication1
    {
      public partial class Form1 : Form
      {
        public Form1()
        {
          InitializeComponent();
          this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(Form1_FormClosing);
          tm.Tick += new System.EventHandler(DoSomethingWithKeyboardInput);
          this.Load += new System.EventHandler(Form1_Load);
          textBox1.KeyDown += new System.Windows.Forms.KeyEventHandler(textbox1_KeyDown);
          textBox1.KeyUp += new System.Windows.Forms.KeyEventHandler(textbox1_KeyDown);
        }
    
        private Timer tm = new Timer();
        private List<System.Windows.Forms.Keys> MovementKeys = new List<System.Windows.Forms.Keys>();
        private _MyInputKeys MyInputKeys = new _MyInputKeys();
    
        private struct _MyInputKeys
        {
          public bool Jump;
          public bool Left;
          public bool Right;
        }
    
        private void Form1_FormClosing(object sender, System.Windows.Forms.FormClosingEventArgs e)
        {
          tm.Stop();
        }
    
        public void DoSomethingWithKeyboardInput(object sender, EventArgs e)
        {
          textBox1.Text = (MyInputKeys.Left ? "(left)" : "") + 
            (MyInputKeys.Right ? "(right)" : "") + (MyInputKeys.Jump ? "(jump)" : "");
        }
    
        private void Form1_Load(object sender, System.EventArgs e)
        {
          //define keys used for movement
    
          MovementKeys.Add(Keys.Up); //Jump ?
          MovementKeys.Add(Keys.Left); //Left Arrow - Move Left
          MovementKeys.Add(Keys.Right); //Rigth Arrow - Move Right
          tm.Interval = 50;
          tm.Start();
        }
    
        private void textbox1_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
        {
          if (MovementKeys.IndexOf(e.KeyCode) != -1)
          {
            e.Handled = true;
            MyInputKeys.Jump = IsKeyDown(Keys.Up);
            MyInputKeys.Left = IsKeyDown(Keys.Left);
            MyInputKeys.Right = IsKeyDown(Keys.Right);
          }
        }
    
        public static bool IsKeyDown(Keys key)
        {
          return (GetKeyState(Convert.ToInt16(key)) & 0X80) == 0X80;
        }
        /// <summary>
        ///  If the high-order bit is 1, the key is down; otherwise, it is up.
        ///  If the low-order bit is 1, the key is toggled. 
        ///  A key, such as the CAPS LOCK key, is toggled if it is turned on. 
        ///  The key is off and untoggled if the low-order bit is 0. 
        ///  A toggle key's indicator light (if any) on the keyboard will be on when 
        ///  the key is toggled, and off when the key is untoggled.
        /// </summary>
        /// <param name="nVirtKey"></param>
        [DllImport("user32.dll")]
        public extern static Int16 GetKeyState(Int16 nVirtKey);
      }
    }
    
    

    Wednesday, January 12, 2011 5:36 PM
  • You have to override the OS's repeat key function.  Detect a key down, do whatever should be done when this key is pressed and start a timer.  Continue  to perform the key down operation on each timer tick until the key is released,  which you detect in the KeyUp event.  As Louis repeats, you have to keep track.
    Wednesday, January 12, 2011 5:55 PM