[Plugin] Keyboard events

MightyGate

Hi all!

We are the "iHUD for" development team. For those who don't know what is "iHUD for", here are some links with stuff:
- http://www.youtube.com/watch?v=YN_2JQu5FPM
- http://www.youtube.com/watch?v=_ZQ__tPgH-E
- http://www.mightygate.com

Now that you now what we are doing, it comes our question. We are currently developing the 2.4 version of "iHUD for" which will include active buttons. Essentially, we will let you press a button on iHUD and it will simulate a keypress on you pc (the important thing is that you decide the key). Our problem is that every attempt to simulate a keyboard input on the InternalsPlugin (using the Windows API - SendInput function) is resolved the same way. It doesn't matter if we try to simulate "a", "b", "c" or "F4", rFactor always takes the input as a 'left ALT' event. Do you know some way to simulate the keyboard that actually works? Here is some code snippet:

void read(string iHudEvent)
{
INPUT input[1];

switch(parseIHUDEvent(iHudEvent))
{
case iHUD_EVENT_NORMAL_KEY_DOWN:
{
char keyChar = iHUDEvent.c_str()[0]; // A normal key down is an Ascii Key
SHORT keyCode = VkKeyScanA(keyChar);
input[0].type = INPUT_KEYBOARD;
input[0].ki.wVk = keyCode;
input[0].ki.dwFlags = 0;
}
break;
case IHUD_EVENT_NORMAL_KEY_UP:
{
char keyChar = iHUDEvent.c_str()[1]; // A normal key up is a '!' followed by an Ascii Key
SHORT keyCode = VkKeyScanA(keyChar);
input[0].type = INPUT_KEYBOARD;
input[0].ki.wVk = keyCode;
input[0].ki.dwFlags = KEYEVENTF_KEYUP;
}
break;
/// .....More switch stuff
}

input[0].ki.wVk = LOBYTE(input[0].ki.wVk);
::SendInput(1,input,sizeof(input));

Sleep(50); // Lets some time to game to recognize the keypress
}

We would appreciate any help! We know it's a very difficult and technical question.

Thank you in advance!! :)

Regards,
The Mightygate team
 
I can't help immediately beyond confirming that it is possible, I've done it. With luck I'll be able to find the code later.
 
I haven't automated the keyboard from a plugin but I have done it from a dotnet app using keybd_event from user32.dll.

Here is the documentation:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646304(v=vs.85).aspx

My app reads the controller.ini to get the scan codes for what ever it is I want to simulate and then I send the scancode like this:

Code:
keybd_event(0, pitDisplay, 0, 0);
Sleep(50);
keybd_event(0, pitDisplay, KEYEVENTF_KEYUP, 0);

pitDisplay being the scancode that I got from reading "Control - Pit Display" in the controller.ini.
 
What I have is a snippet that shakes the drivers head by doing a look left / look right. It's odd the way you have to check for the input you want and return a float if it is. I did develop this into some code to control the pit menu but I can't find it.

Code:
bool ExampleInternalsPlugin::CheckHWControl( const char * const controlName, float &fRetVal )
{
  // only if enabled, of course
  if( !mEnabled )
    return( false );

  if (check_pitDisplay(controlName, mET))
  {
    fRetVal = 1.0f;
    return( true );
  }

  // Note that incoming value is the game's computation, in case you're interested.

  // Sorry, no control allowed over actual vehicle inputs ... would be too easy to cheat!
  // However, you can still look at the values.

  if (do_shake)
  {
    // Note: since the game calls this function every frame for every available control, you might consider
    // doing a binary search if you are checking more than 7 or 8 strings, just to keep the speed up.
    if( _stricmp( controlName, "LookLeft" ) == 0 )
    {
      const float headSwitcheroo = fmodf( mET, 2.0f );
      if( headSwitcheroo < 0.5 )
        fRetVal = 1.0f;
      else
        fRetVal = 0.0f;
      return( true );
    }
    else if( _stricmp( controlName, "LookRight" ) == 0 )
    {
      const float headSwitcheroo = fmodf( mET, 2.0f );
      if( ( headSwitcheroo > 1.0f ) && ( headSwitcheroo < 1.5f ) )
        fRetVal = 1.0f;
      else
        fRetVal = 0.0f;
      return( true );
    }
  }
  return( false );
}
 
Maybe I am a little slow today but what does that code snippet have to do with sending keyboard inputs to rFactor?
 
Thanks everyone!! We will try all your solutions and hope at least one works for us :)
 
Using keybd_event as Noel describes above has worked for me, too. A single 'frame' in UpdateTelemetry (press this time, lift next time) works fine.
 

Back
Top