2

I am doing a small project to issue keyboard messages based on the position of a joystick.

The keyboard messages are simulated using SendInput().

Individual keys work properly. My problem is with simulating a key that is held down for a long period. If I use SendInput at every pass of the loop, it is like pressing the key multiple times.

I read on msdn that there is a field with flags to indicate the key's previous state, and other flags.

How do you make modifications to such a field? from where do you get access to it?

UPDATE

Here is the code for the positive X axis:

#include<Windows.h>
#include<iostream>

using namespace std;

#define mid 32767
#define trig 1804
#define reset 1475

// Virtual codes
#define XU 0x44 //D
#define XL 0x41 //A
#define YU 0x53 //S
#define YL 0x57 //W
#define ZU 0x51 //Q
#define ZL 0x45 //E

// Scan codes

#define sXU 0x20 //D
#define sXL 0x1E //A
#define sYU 0x1F //S
#define sYL 0x11 //W
#define sZU 0x10 //Q
#define sZL 0x12 //E

int main()
{
    UINT result;
    JOYINFO pos;
    INPUT xi, yi, zi;

    int i = 0;
    int state[6] = { 0,0,0,0,0,0 };
    int uu = mid + trig;
    int ul = mid + reset;
    int ll = mid - trig;
    int lu = mid - reset;

    xi.type = INPUT_KEYBOARD;
    yi.type = INPUT_KEYBOARD;
    zi.type = INPUT_KEYBOARD;

    while (1)
    {
        result = joyGetPos(i, &pos);

        if (result != JOYERR_NOERROR) // Check to which ID is the joystick assigned
        {
            cout << "JoyID " << i << " returned an error. Trying the next one." << endl;
            i++;
            if (i > 15)
            {
                cout << "Reached the maximum allowed attempts. Exiting." << endl;
                return 1;
            }               
        }
        else // start simulating key preses based on the joystick’s position
        {
            //-----------------------------------------------------------------
            //
            // X-axis positive
            //
            //-----------------------------------------------------------------

            if (pos.wXpos > uu)
            {
                if (state[0] == 1) // Second pass of the loop, re-issue the same key with “previous state” flag as 1
                {
                    xi.ki.wVk = XU;
                    xi.ki.wScan = sXU;
                    xi.ki.dwFlags = KEYEVENTF_SCANCODE;
                    xi.ki.dwExtraInfo = 0x40000000;
                    SendInput(1, &xi, sizeof(INPUT));
                    state[0] = 1;
                }
                if (state[0] == 0) // First pass of the loop, issue the key
                {
                    xi.ki.wVk = XU;
                    xi.ki.wScan = sXU;
                    xi.ki.dwFlags = KEYEVENTF_SCANCODE;
                    SendInput(1, &xi, sizeof(INPUT));
                    state[0] = 1;                   
                }               
            }
            if (pos.wXpos < ul && state[0] != 0) // When the joystick returns to the centre, simulate a key up.
            {
                xi.ki.wVk = XU;
                xi.ki.wScan = sXU;
                xi.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
                //xi.ki.dwExtraInfo = 0x00000000;
                SendInput(1, &xi, sizeof(INPUT));
                state[0] = 0;
            }
            Sleep(15);
        }
    }
    return 0;
}

If you try this out you will see that the key is issued only twice. If I modify the condition to re-issue the key at every pass, you will see that it is not like a keyboard's autorepeat.

I think the issue resides with the flags dwExtraInfo. At present I am over-riding whatever there is because I do not know how to read the existing state, given that I do not pass any lparam to any window. Do you have any ideas?

Thanks.

JayD
  • 53
  • 1
  • 6
  • Possible duplicate of [How to simulate holding down a keyboard button in C++](https://stackoverflow.com/questions/30936776/how-to-simulate-holding-down-a-keyboard-button-in-c) – Killzone Kid Mar 31 '18 at 19:03
  • "*If I use SendInput at every pass of the loop, it is like pressing the key multiple times.*" - are you sending a key up event on each loop iteration? – Remy Lebeau Mar 31 '18 at 23:28
  • The keyup is sent only at the last iteration. It does actually "repeat" keys but it is not the typical behaviour. For example, in notepad, if you press a key and keep it, it will issue the character, then after a short time, it will start repetition. With a sendinput at every pass, it just repeats the character depending on the loop wait time. – JayD Apr 01 '18 at 07:33
  • There are not many games that are so primitive that they need to rely on the keyboard controller repeating a key. Any WASD game will only use the first keydown and the keyup notification to change the game object state. – Hans Passant Apr 01 '18 at 15:26
  • 1
    At this stage it is not about games. With the above code, notepad or word do not repeat the keys if I keep the joystick to the right. On the other hand, if I keep a button pressed on the on screen keyboard, they repeat the keys just like a physical keyboard. I am trying to simulate that. – JayD Apr 01 '18 at 15:35

0 Answers0