Search code examples
cwinapisendinput

Cannot found any data type used by SendInput() function


I'm trying to use SendInput() function. I wrote this code:

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <winuser.h>

#define WIN32_LEAN_AND_MEAN

//...

    KEYBDINPUT kbi;
    kbi.wVk = 0x31;
    kbi.wScan = 0;
    kbi.dwFlags = 0;
    kbi.time = 0;

    INPUT input;
    input.type = INPUT_KEYBOARD;
    input.ki = kbi;

    SendInput(1, &input, sizeof input);

Compiling:

gcc -Wall -o window.exe win32.c -lWs2_32

I get:

win32.c: In function ‘main’:
win32.c:13:2: error: ‘KEYBDINPUT’ undeclared (first use in this function)
win32.c:13:2: note: each undeclared identifier is reported only once for each function it appears in
win32.c:13:13: error: expected ‘;’ before ‘kbi’
win32.c:14:2: error: ‘kbi’ undeclared (first use in this function)
win32.c:20:2: error: ‘INPUT’ undeclared (first use in this function)
win32.c:20:8: error: expected ‘;’ before ‘input’
win32.c:21:2: error: ‘input’ undeclared (first use in this function)
win32.c:21:15: error: ‘INPUT_KEYBOARD’ undeclared (first use in this function)

I have no idea how to fix tihis. According the documentation it's declared in Winuser.h header. But don't works for me.


Solution

  • #define _WIN32_WINNT 0x0403
    #include <windows.h>
    

    Seems this is the magic #define you need somewhere in your project (either explicitly in code, or via compiler command line param -D).

    Note that windows.h includes winuser.h, so there's no need to include that, as it's included already for you. Also, the WIN32_LEAN_AND_MEAN define only has any effect if it's included before windows. Details about what it does here; it's not needed or particularly useful these days.

    --

    So what's going on here? Looking for the definition of KBDINPUT in winuser.h (C:\Cygwin\usr\include\w32api\winuser.h), we see:

    #if (_WIN32_WINNT >= 0x0403)
    typedef struct tagMOUSEINPUT {
    ...
    } MOUSEINPUT,*PMOUSEINPUT;
    typedef struct tagKEYBDINPUT {
    ...
    

    That's the problem; these only get defined if _WIN32_WINNT is greater than 0x0403.

    Those are the files from the cygwin package. Interestingly, the winuser.h from the Microsoft SDK (usually installed in C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\WinUser.h) uses a different condition:

    #if (_WIN32_WINNT > 0x0400)
    

    ...which explains Jay's suggestion - he's likely looking at the MS files, where 0x0401 would be sufficient here; and also explains why it's not working for you - you're likely using the cygwin ones with a higher version requirement. As to why these two files are different - I've no idea there...