How to trap keystrokes in .NET controls by using Visual C++ .NET or Visual C++ 2005 (816190)



The information in this article applies to:

  • Microsoft Visual C++ .NET (2003)
  • Microsoft .NET Framework 1.1
  • Microsoft Visual C++ 2005 Express Edition

For a Microsoft Visual Basic .NET version of this article, see 320583.
For a Microsoft Visual C# .NET version of this article, see 320584.

This article refers to the following Microsoft .NET Framework Class Library namespaces:
  • System::ComponentModel
  • System::Collections
  • System::Windows::Forms
  • System::Data
  • System::Drawing
You can capture different keystrokes programmatically by overriding the ProcessCmdKey method of the controls in your code. This feature is frequently requested for the DataGrid control. You use the keyboard more frequently to edit or to view the data that appears in the DataGrid control.

IN THIS TASK

INTRODUCTION

This step-by-step article describes how to capture keystrokes in Windows Forms controls. By using the sample code in this article, you can intercept most individual keystrokes. You also can intercept key combinations, including CTRL and ALT. This technique does not capture the PRINT SCREEN key. Additionally, some keystrokes from keyboards with additional keys, such as keys that control a Web browser or a CD-ROM player, may not be captured.

For most purposes, the standard KeyUp event, the standard KeyDown event, and the standard KeyPress event are sufficient to capture and to handle keystrokes. However, not all controls raise these events for all keystrokes and under all conditions.

The DataGrid control is an example of a control that does not raise all events for all keystrokes under all conditions. If no data has been assigned to the grid in the DataGrid control, the arrow keys, such as the LEFT ARROW key, the RIGHT ARROW key, the UP ARROW key, and the DOWN ARROW key, raise only the KeyUp event. Other keys, such as the A key or the 4 key, raise all three events. If the DataGrid control currently displays data, none of the standard keyboard events are raised for the navigation keys. Keys such as the A key or the 4 key may raise no events, may raise only the KeyUp event, or may raise all three events. What event is raised depends on what options are currently set in the DataGrid control. However, you can follow the steps in this article to capture keystrokes, regardless of the state of the DataGrid control.

The code samples in this article are written to work with the DataGrid control. Handling different keystrokes with the DataGrid control is the most frequently requested feature. You can use the same approach with other Microsoft .NET controls.

back to the top

Requirements

The following list outlines the recommended hardware, software, network infrastructure, and service packs that you need:
  • Microsoft Visual Studio .NET 2003 or Microsoft Visual Studio 2005
  • Microsoft .NET Framework 1.1 or a later version of the .NET Framework
This article assumes that you are familiar with the following topics:
  • Handling and raising events with Visual Studio .NET 2003 or Microsoft Visual Studio 2005
  • Programming with the DataGrid control
back to the top

Set up the keystroke trap to capture keystrokes

To capture keystrokes in a Microsoft Windows Forms control, you must derive a new class that is based on the class of the control that you want to capture keystrokes in. When you do this, you override the ProcessCmdKey method. You put the code in the ProcessCmdKey method that processes the keystrokes that you want to capture. The following sample code shows the basic structure for such a class:
public __gc class MyDataGridControl : public System::Windows::Forms::DataGrid
    {
    protected:
        bool ProcessCmdKey(Message* msg, Keys keyData)  
        {
        }
    }
back to the top

Implement the ProcessCmdKey method

The system passes two parameters to the ProcessCmdKey method. They are:
  • The msg parameter
  • The keyData parameter
The msg parameter contains the Windows Message, such as the WM_KEYDOWN message. The keyData parameter contains the key code of the key that was pressed. If the ALT control key or the CTRL control key was also pressed, the keyData parameter contains the ModifierKey information.

You do not have to use the msg parameter. However, in actual practice, testing the message is a good idea. In this example, you test the WM_KEYDOWN message to verify whether this is a keystroke event. You also test the WM_SYSKEYDOWN message so that you can capture keystroke combinations that include control keys. The primary control keys that you want to capture are the ALT control key and the CTRL control key.

To capture specific keys, you can evaluate the key code by comparing the keyCode to the Keys enumeration data type. The following code sample demonstrates how to capture the UP ARROW key, the DOWN ARROW key, the TAB key, the CTRL+M key combination, and the ALT+Z key combination:
const int WM_KEYDOWN = 0x100;
const int WM_SYSKEYDOWN = 0x104;

if ((msg->Msg == WM_KEYDOWN) || (msg->Msg == WM_SYSKEYDOWN))
{
	switch(keyData)
	{
	case Keys::Down:
			this->Parent->Text = S"DOWN ARROW key captured";
			break;
		
	case Keys::Up:
			this->Parent->Text = S"UP ARROW key captured";
			break;
	
	case Keys::Tab:
			this->Parent->Text = S"TAB key captured";
			break;
	
	case Keys::Control | Keys::M:
			this->Parent->Text = S"CTRL+M key combination captured";
			break;
	
	case Keys::Alt | Keys::Z:
			this->Parent->Text = S"ALT+Z key combination captured";
			break;
	}				
}
back to the top

Build an example

The following example shows how to capture keystrokes with the DataGrid control.

Build MyDataGridControl UserControl

  1. Start Visual Studio .NET 2003 or Microsoft Visual Studio 2005.
  2. On the File menu, point to New, and then click Project.

    The New Project dialog box appears.
  3. Under Project Types, click Visual C++ Projects.

    Note In Visual Studio 2005, click Visual C++ under Project Types.
  4. Under Templates, click Windows Control Library (.NET).

    Note In Visual Stuido 2005, click Windows Forms Control Library under Templates.
  5. In the Name box, type MyDataGrid, and then click OK.
  6. On the View menu, click Code to open the code window of the UserControl control.
  7. Locate the following code for the Control library.
    public __gc class MyDataGridControl : public System::Windows::Forms::UserControl
    Change the previous code to the following code:
    public __gc class MyDataGridControl : public System::Windows::Forms::DataGrid
  8. Add the following method to the MyDataGridControl class:
    protected:
        bool ProcessCmdKey(Message* msg, Keys keyData)  
        {
            const int WM_KEYDOWN = 0x100;
            const int WM_SYSKEYDOWN = 0x104;
    
            if ((msg->Msg == WM_KEYDOWN) || (msg->Msg == WM_SYSKEYDOWN))
            {
                switch(keyData)
                {
                case Keys::Down:
                        this->Parent->Text = S"DOWN ARROW key captured";
                        break;
                    
                case Keys::Up:
                        this->Parent->Text = S"UP ARROW key captured";
                        break;
                
                case Keys::Tab:
                        this->Parent->Text = S"TAB key captured";
                        break;
                
                case Keys::Control | Keys::M:
                        this->Parent->Text = S"CTRL+M key combination captured";
                        break;
                
                case Keys::Alt | Keys::Z:
                        this->Parent->Text = S"ALT+Z key combination captured";
                        break;
                }               
            }
    
            return (__super::ProcessCmdKey(msg,keyData));
        }
    Note You must add the common language runtime support compiler option (/clr:oldSyntax) in Visual C++ 2005 to successfully compile this code sample. To do this, follow these steps:
    1. Click Project, and then click ProjectName Properties.

      Note ProjectName represents the name of the project.
    2. Expand Configuration Properties, and then click General.
    3. Click to select Common Language Runtime Support, Old Syntax (/clr:oldSyntax) in the Common Language Runtime support project setting on the right pane, click Apply, and then click OK.
    For more information about the common language runtime support compiler options, visit the following Microsoft Web site:

    /clr (Common Language Runtime Compilation)
    http://msdn2.microsoft.com/en-us/library/k8d11d4s.aspx

  9. Press CTRL+SHIFT+S to save the project.
  10. Press CTRL+SHIFT+B to build the solution.

    This builds the MyDataGridControl UserControl and then creates a .dll file.
  11. On the File menu, click Close Solution.
back to the top

Create a new project

  1. On the File menu, point to New, and then click Project.

    The New Project dialog box appears.
  2. Under Project Types, click Visual C++ Projects.

    Note In Visual Studio 2005, click Visual C++ under Project Types.
  3. Under Templates, click Windows Forms Application (.NET).

    Note In Visual Stuido 2005, click Windows Forms Application under Templates.
  4. In the Name box, type DataGridTrapKey, and then click OK.

    By default, the Form1 form is created and then opened in Design mode.
  5. On the Tools menu, click Add/Remove Toolbox Items.
  6. Click the .NET Framework Components tab.
  7. Click Browse, and then locate the MyDataGrid.dll file that you previously created.
  8. Click OK.

    Notice that the MyDataGridControl control is added to the Toolbox.
  9. Add a MyDataGridControl control to the Form1 form.
  10. Right-click Form1, and then click View Code.
  11. Add the following code to the top of the Form1 class:
    // This structure is only used to provide sample data for the grid.
    public:
        __gc struct gridData
        {
        private:
            String *make;
            int year;
    
        public:
            gridData(String *n,int y)
            {
                make=n;
                year=y;
            }
    
            __property String* get_Make()
            {
                return make;
            }
    
            __property void set_Make(String* Make)
            {
                make = (Make);
            }
    
            __property int get_Year()
            {
                return year;
            }
    
            __property void set_Year(int Year)
            {
                year = Year;
            }
        };
  12. Declare the following variable in the Form1 class:
    protected:
            __gc struct gridData *dataArray[];
  13. Add the following code to the Form1 class constructor after the call to the InitializeComponent method:
    dataArray = new gridData *[5];
  14. On the View menu, click Designer to switch to Design mode.
  15. Double-click Form1 to add a Form1_Load event handler to the code window.
  16. Add the following code to the Form1_Load event handler:
    // Create some sample data.
    dataArray[0] = new gridData(S"ford",1999);
    dataArray[1] = new gridData(S"chevrolet",1999);
    dataArray[2] = new gridData(S"plymouth",1988);
    dataArray[3] = new gridData(S"honda",1999);
    dataArray[4] = new gridData(S"fiat",1987);
    
    // Assign the data to the grid.
    myDataGridControl1->DataSource = dataArray;
  17. Press CTRL+SHIFT+S to save the project.
  18. Press CTRL+SHIFT+B to build the solution.
  19. Press CTRL+F5 to run the project.
  20. Try the various keystrokes that have been captured, such as the UP ARROW key, the DOWN ARROW key, the TAB key, the CTRL+M key combination, and the ALT+Z key combination. The caption of the form is updated to show the key or the key combination that was pressed.
back to the top

REFERENCES

For more information about the ProcessCmdKey method, visit the following Microsoft Developer Network (MSDN) Web site:back to the top

Modification Type:MajorLast Reviewed:1/5/2006
Keywords:kbWindowsForms kbForms kbCtrl kbControl kbCollections kbHOWTOmaster KB816190 kbAudDeveloper