Shane
Shane

Reputation: 2057

Issue with WinAPI SendInput code

I am writing a program, and it is going well so far, however I have an issue with the following code:

void Send(string content) {
    unsigned int size = content.size();
    INPUT *inputs = new INPUT[size];

    for (unsigned int i = 0; i < size; i++) {
        inputs[i].type = 1;
        inputs[i].ki.wVk          = 0;//LOWORD(VkKeyScan(content.at(i)));
        inputs[i].ki.wScan        = content.at(i);
        inputs[i].ki.dwFlags      = KEYEVENTF_UNICODE | KEYEVENTF_SCANCODE;
        inputs[i].ki.time         = 0;
        inputs[i].ki.dwExtraInfo  = ::GetMessageExtraInfo();
    }

    SendInput(size, inputs, sizeof(*inputs)*size);

    for (unsigned int i = 0; i < size; i++) {
        inputs[i].ki.dwFlags &= KEYEVENTF_KEYUP;
    }

    SendInput(size, inputs, sizeof(*inputs)*size);
}

What I am trying to achieve is being able to send input like this:

Send(string("Hello World!"));

However, it does everything it should not, such as moving the cursor even though the type is set to the keyboard. At most, it outputs one character. As you see on line 2, I have an INPUT array. However, when I view this in the debugger, it appears simply as a single INPUT structure, rather than an array of structures.

I am using g++ with gdb debugger + Code::Blocks IDE.

Thanks guys.

EDIT

NEW CODE:

void Send(string content) {
    unsigned int size = content.size();
    INPUT *inputs = new INPUT[size];
    INPUT curr[1];

    ZeroMemory(inputs, sizeof(*inputs)*size);

    for (unsigned int i = 0; i < size; i++) {
        inputs[i].type = 1;
        inputs[i].ki.wVk          = 0;//LOWORD(VkKeyScan(content.at(i)));
        inputs[i].ki.wScan        = content.at(i);
        inputs[i].ki.dwFlags      = KEYEVENTF_UNICODE | KEYEVENTF_SCANCODE;
        inputs[i].ki.time         = 0;
        inputs[i].ki.dwExtraInfo  = ::GetMessageExtraInfo();
    }

    for (unsigned int i = 0; i < size; i++) {
        curr[0] = inputs[i];            // Current input
        int a = ::SendInput(1, (INPUT*)&curr, sizeof(curr));

        inputs[i].ki.dwFlags &= KEYEVENTF_KEYUP;

        curr[0] = inputs[i];
        int b = ::SendInput(1, (INPUT*)&curr, sizeof(curr));

        TCHAR *buff = new TCHAR[3];

        wsprintf(buff, "%i %i", a, b);

        MessageBox(NULL, buff, "SendInput return vals", 0);
    }
}

This still sends nothing.

Upvotes: 3

Views: 1507

Answers (2)

marcinj
marcinj

Reputation: 50046

I suppose it is because you are sending only KEYDOWN messages. You might want to try sending first KEYDOWN, then KEYEVENTF_KEYUP for the same character.

[edit for NEW CODE]

few hints:

  1. remove KEYEVENTF_SCANCODE
  2. string is for char strings, for UNICODE use wstring
  3. before testing your function make sure that some app with editbox is foreground, for example Notepad

Upvotes: 1

Ben Voigt
Ben Voigt

Reputation: 283921

sizeof(*inputs)*size

This is wrong, the cbSize parameter is the size of one INPUT structure, not the total size of the array.

You would have discovered this if you hadn't thrown away the SendInput return value. checking return values is the most basic troubleshooting possible when things go wrong.

You also have a memory leak. And you should use ZeroMemory on the array before filling it in.

Finally, you're pressing all the keys before releasing any of them. If you want to type text, you should press and release each key in sequence, so that no more than one key is pressed at a time.

Upvotes: 2

Related Questions