none
pressing arrow keys as hot-keys changes control focus

    General discussion

  • I want to define the Left and Right arrow keys as "hot keys" in my form. I've handled KeyDown, and I set the Handled property of the event, but if the current focus is on a button, radio, check box, etc, then the arrow keys cycle the input focus through controls on the form, or within the same group box.

    How can I disable this behavior?
    Friday, October 10, 2003 2:48 PM

All replies

  • Here's what you need to do:  Override the form's ProcessDialogKey method, and return false if the key is Left or Right.  This will prevent the form from sending the keystroke on to the child controls.

    Also, the form's KeyPreview property MUST be set to true.  This allows the form to preview what keys are being pressed before allowing them to be passed on to the appropriate events.

    So what you have is the form's ProcessDialogKey overridden, KeyPreview set to true, and the form's KeyDown event handled.  That should take care of the problem.

    Here's what the ProcessDialogKey method should look like on your form.  It's in C#; let me know if you need it in VB.

    public class MyForm : System.Windows.Forms.Form
    {
       // Normal stuff goes here

       private void MyForm_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
       {
          // Call your method or whatnot here; this is where you handle the actual key press
          // Set e.Handled as necessary.
       }
       
       protected override bool ProcessDialogKey(Keys keyData)
       {
          if (keyData.Equals(Keys.Left) || keyData.Equals(Keys.Right))
             return false;
          else
             // Pass it on to the base class for processing
             return base.ProcessDialogKey(keyData);
       }
    }


    More info on ProcessDialogKey is available here:
    <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemwindowsformscontrolclassprocessdialogkeytopic.asp">http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemwindowsformscontrolclassprocessdialogkeytopic.asp</a>

    Hope this helps.

    -Ari
    Monday, October 13, 2003 6:46 PM
  • Well, from looking at the ProcessDialogKeys, you should be returning True, right? But I tried both, and neither of them seem to work. It's especially visible when a group box and a bunch of radio buttons have the focus.
    Monday, October 13, 2003 8:23 PM
  • You're right -- there is a mistake in my code.  You should be returning true if you don't want to process the keystroke anymore; otherwise, you want to return the call to the base class's ProcessDialogKeys.  Though interestingly, false worked as well.  Weird.

    Have you set the form's KeyPreview to true?  If you haven't, none of this will work.  This allows the form to see the keystrokes before they're processed.

    Hmm... if that doesn't work, let me know.  I wrote a sample app in C# that illustrates this working (actually, that's all it does -- 3 buttons, a groupbox, and 3 radiobuttons, and if you hit left or right you get a messagebox and nothing else).  I can post it here if necessary.

    -Ari
    Tuesday, October 14, 2003 1:06 PM
  • I think I'm using some control groups which must hook to something deeper. Thanks for the effort.
    Thursday, October 16, 2003 1:29 PM
  • Well, here's the code I used, so feel free to try it.  It catches left and right and throws up a MessageBox when it's caught.  The code works -- I just tested it myself -- so maybe it'll help.

    using System;
    using System.Drawing;
    using System.Collections;
    using System.ComponentModel;
    using System.Windows.Forms;
    using System.Data;

    namespace WindowsApplication12
    {
       /// <summary>
       /// Summary description for Form1.
       /// </summary>
       public class Form1 : System.Windows.Forms.Form
       {
          private System.Windows.Forms.Button button1;
          private System.Windows.Forms.Button button2;
          private System.Windows.Forms.Button button3;
          private System.Windows.Forms.GroupBox groupBox1;
          private System.Windows.Forms.RadioButton radioButton1;
          private System.Windows.Forms.RadioButton radioButton2;
          private System.Windows.Forms.RadioButton radioButton3;
          /// <summary>
          /// Required designer variable.
          /// </summary>
          private System.ComponentModel.Container components = null;

          public Form1()
          {
             //
             // Required for Windows Form Designer support
             //
             InitializeComponent();

             //
             // TODO: Add any constructor code after InitializeComponent call
             //
          }

          /// <summary>
          /// Clean up any resources being used.
          /// </summary>
          protected override void Dispose( bool disposing )
          {
             if( disposing )
             {
                if (components != null) 
                {
                   components.Dispose();
                }
             }
             base.Dispose( disposing );
          }

          #region Windows Form Designer generated code
          /// <summary>
          /// Required method for Designer support - do not modify
          /// the contents of this method with the code editor.
          /// </summary>
          private void InitializeComponent()
          {
             this.button1 = new System.Windows.Forms.Button();
             this.button2 = new System.Windows.Forms.Button();
             this.button3 = new System.Windows.Forms.Button();
             this.groupBox1 = new System.Windows.Forms.GroupBox();
             this.radioButton1 = new System.Windows.Forms.RadioButton();
             this.radioButton2 = new System.Windows.Forms.RadioButton();
             this.radioButton3 = new System.Windows.Forms.RadioButton();
             this.groupBox1.SuspendLayout();
             this.SuspendLayout();
             // 
             // button1
             // 
             this.button1.Location = new System.Drawing.Point(200, 8);
             this.button1.Name = "button1";
             this.button1.TabIndex = 0;
             this.button1.Text = "button1";
             // 
             // button2
             // 
             this.button2.Location = new System.Drawing.Point(200, 48);
             this.button2.Name = "button2";
             this.button2.TabIndex = 1;
             this.button2.Text = "button2";
             // 
             // button3
             // 
             this.button3.Location = new System.Drawing.Point(200, 88);
             this.button3.Name = "button3";
             this.button3.TabIndex = 2;
             this.button3.Text = "button3";
             // 
             // groupBox1
             // 
             this.groupBox1.Controls.Add(this.radioButton3);
             this.groupBox1.Controls.Add(this.radioButton2);
             this.groupBox1.Controls.Add(this.radioButton1);
             this.groupBox1.Location = new System.Drawing.Point(48, 136);
             this.groupBox1.Name = "groupBox1";
             this.groupBox1.TabIndex = 3;
             this.groupBox1.TabStop = false;
             this.groupBox1.Text = "groupBox1";
             // 
             // radioButton1
             // 
             this.radioButton1.Location = new System.Drawing.Point(3, 16);
             this.radioButton1.Name = "radioButton1";
             this.radioButton1.TabIndex = 0;
             this.radioButton1.Text = "radioButton1";
             // 
             // radioButton2
             // 
             this.radioButton2.Location = new System.Drawing.Point(120, 40);
             this.radioButton2.Name = "radioButton2";
             this.radioButton2.Size = new System.Drawing.Size(72, 24);
             this.radioButton2.TabIndex = 1;
             this.radioButton2.Text = "radioButton2";
             // 
             // radioButton3
             // 
             this.radioButton3.Location = new System.Drawing.Point(8, 64);
             this.radioButton3.Name = "radioButton3";
             this.radioButton3.TabIndex = 2;
             this.radioButton3.Text = "radioButton3";
             // 
             // Form1
             // 
             this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
             this.ClientSize = new System.Drawing.Size(292, 266);
             this.Controls.Add(this.groupBox1);
             this.Controls.Add(this.button3);
             this.Controls.Add(this.button2);
             this.Controls.Add(this.button1);
             this.KeyPreview = true;
             this.Name = "Form1";
             this.Text = "Form1";
             this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown);
             this.groupBox1.ResumeLayout(false);
             this.ResumeLayout(false);

          }
          #endregion

          /// <summary>
          /// The main entry point for the application.
          /// </summary>
          [STAThread]
          static void Main() 
          {
             Application.Run(new Form1());
          }

          private void Form1_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
          {
             // You can try uncommenting this code, but it works with the code commented
             //e.Handled = true;
             //MessageBox.Show(e.KeyValue.ToString());
          }

          protected override bool ProcessDialogKey(Keys keyData)
          {
             if (keyData.Equals(Keys.Left) || keyData.Equals(Keys.Right))
             {
                MessageBox.Show("caught");
                return true;
             }
             else
             {
                return base.ProcessDialogKey(keyData);
             }
          }

       }
    }


    -Ari
    Thursday, October 16, 2003 6:09 PM
  • This example code works great but what if you want to trap the use of a modifier key as well (eg. SHIFT + LEFT ARROW)?

    Your help would be much appreciated!

    Thanks Dave
    Monday, April 19, 2004 5:52 PM
  • Trapping the modifier keys is just as easy -- just do a bitwise OR on the keyData.Equals() call to check for modifier keys.  So in this example, to use Shift you would change this:if (keyData.Equals(Keys.Left) || keyData.Equals(Keys.Right))to this:if (keyData.Equals(Keys.Left | Keys.Shift) || keyData.Equals(Keys.Right | Keys.Shift))

    Hope this helps.

    -Ari
    Monday, April 19, 2004 6:35 PM
  • Thanks Ari - that works perfectly!!
    Monday, April 19, 2004 6:37 PM