4
votes

I am using this keyboard hook for my project. I am unable to send small letters using SendKeys.Send() with SHIFT modifier key pressed. My app needs (for example) if the user presses K button "a" should be sent and if he presses SHIFT+K, "b" should be sent. The code is:

void gkh_KeyDown(object sender, KeyEventArgs e)
{
    if (e.KeyCode == Keys.K)
    {
        if (Control.ModifierKeys == Keys.Shift)
            SendKeys.Send("b");
        else
            SendKeys.Send("a");
    }
    e.Handled == true;   
}

But it sends "B" (Capital letter) instead of "b", that is the SHIFT key changes the sent keystroke "b" to uppercase. This happens even after adding Keys.Shift to the hook.

I tried many approaches including using e.SupressKeyPress, SendKeys("b".toLower()) and putting above code in KeyUp event but in vein.

Pls help me, I am very frustated, my application developement is struck at this point.

1

1 Answers

4
votes

You're sending the keys while the Shift key is still down, which is causing them to be uppercased.
You need to figure out a way to cancel the Shift key press along with the K key press.

The global hook sample that you're using is a little bare; it should also be reporting which modifier keys are held down. Unfortunately, it looks like that functionality hasn't been implemented.

Why do you need to use a keyboard hook in the first place? Do you really need to handle key events that occur when your form doesn't have the focus? And if so, why in the world would you use SendKey? How do you know what the currently active application is going to do with the key presses you send?

This looks like something that would be much better handled in an override of your form's ProcessCmdKey method, instead. For example:

  protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
  {
     if (keyData == (Keys.K | Keys.Shift))
     {
        SendKeys.Send("b");
        return true;  // indicate that you handled the key
     }
     else if (keyData == Keys.K)
     {
        SendKeys.Send("a");
        return true;  // indicate that you handled the key
     }

     // call the base class to handle the key
     return base.ProcessCmdKey(ref msg, keyData);
  }

EDIT: Your comment suggests that you do in fact need to handle key events that occur when you form does not have the focus. Assuming you need to handle more than simply the K key, you will need to do this using a global hook.

As I mentioned before, the problem is that the user is still holding down the Shift key while you're sending the B key using SendInput, which is causing it to register as a capital letter B instead of a lowercase letter. So then the solution is obvious: you need to figure out a way to cancel that Shift key press so that it is not processed by the operating system. Of course, if you eat the key event, you also need to figure out a way of tracking it so that your application still knows when it was pressed and can act accordingly.

A quick search reveals a similar question has already been asked and answered about the Windows logo key.

In particular, you need to write the code that handles the KeyDown event raised by your global hook like this (at least, this code works with the global hook class that I wrote; it should work with yours, too, but I haven't actually tested it):

// Private flag to hold the state of the Shift key even though we eat it
private bool _shiftPressed = false;

private void gkh_KeyDown(object sender, KeyEventArgs e)
{
   // See if the user has pressed the Shift key
   // (the global hook detects individual keys, so we need to check both)
   if ((e.KeyCode == Keys.LShiftKey) || (e.KeyCode == Keys.RShiftKey))
   {
      // Set the flag
      _shiftPressed = true;

      // Eat this key event
      // (to prevent it from being processed by the OS)
      e.Handled = true;
   }


   // See if the user has pressed the K key
   if (e.KeyCode == Keys.K)
   {
      // See if they pressed the Shift key by checking our flag
      if (_shiftPressed)
      {
         // Clear the flag
         _shiftPressed = false;

         // Send a lowercase letter B
         SendKeys.Send("b");
      }
      else
      {
         // Shift was not pressed, so send a lowercase letter A
         SendKeys.Send("a");
      }

      // Eat this key event
      e.Handled = true;
   }
}