Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 2998
  • Last Modified:

USE SendInput() TO TOGGLE THE STATE OF CAPS LOCK

hey every1...

im trying to make a caps lock alternator, so that ordinary typing will come out like: tHiS Is a tEsT

it uses a windows hook to determine when a key is pressed, and then determines whether caps lock is in effect by using GetAsyncKeyState(20) in the HookProc.

how can i use SendInput to turn caps lock on or off?

i looked this up in the msdn library, but there r so many different parameters which i dont know what to assign to :(

can some1 explain exactly how to do this? some working c++ source code would also be very helpful



thanks in advance,

suma
0
suma_ds
Asked:
suma_ds
  • 4
  • 4
1 Solution
 
AlexFMCommented:
This is function I use to turn Caps Lock on/off:

// bState = TRUE - turn Caps Lock on
// bState = FALSE - turn Caps Lock off
void SetCapsLock(BOOL bState)
{
    BYTE keyState[256];

    GetKeyboardState((LPBYTE)&keyState);
    if( (bState && !(keyState[VK_CAPITAL] & 1)) ||
        (!bState && (keyState[VK_CAPITAL] & 1)) )
    {
        // Simulate a key press
        keybd_event( VK_CAPITAL,
                     0,
                     KEYEVENTF_EXTENDEDKEY | 0,
                     0 );

        // Simulate a key release
        keybd_event( VK_CAPITAL,
                     0,
                     KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP,
                     0);
    }
}
0
 
suma_dsAuthor Commented:
nice... it works :)

but check out what msdn has to say about keybd_event:

"Windows NT/2000/XP:This function has been superseded. Use SendInput instead."

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/WinUI/WindowsUserInterface/UserInput/KeyboardInput/KeyboardInputReference/KeyboardInputFunctions/keybd_event.asp

will the code still be compatible with all versions of windows?
0
 
AlexFMCommented:
You can translate this to SendInput if you want.

VOID keybd_event(
  BYTE bVk,               // virtual-key code
  BYTE bScan,             // hardware scan code
  DWORD dwFlags,          // function options
  ULONG_PTR dwExtraInfo   // additional keystroke data
);

typedef struct tagKEYBDINPUT {
  WORD      wVk;
  WORD      wScan;
  DWORD     dwFlags;
  DWORD     time;
  ULONG_PTR dwExtraInfo;
} KEYBDINPUT, *PKEYBDINPUT;

wVk= bVk
wScan = 0
Flags are the same.
time = 0
dwExtraInfo = 0
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
suma_dsAuthor Commented:
ok that works, but is it really necessary because:

keybd_event(VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY | 0, 0); //caps lock key down                        
keybd_event(VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); //caps lock key up

is a hell of a lot smaller than it's SendImput equivilant:

KEYBDINPUT keyDown;
keyDown.wVk = VK_CAPITAL;
keyDown.wScan = 0;
keyDown.time = 0;
keyDown.dwFlags = KEYEVENTF_EXTENDEDKEY | 0; //keydown
keyDown.dwExtraInfo = 0;

KEYBDINPUT keyUp;
keyUp.wVk = VK_CAPITAL;
keyUp.wScan = 0;
keyUp.time = 0;
keyUp.dwFlags = KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP; //keyup
keyUp.dwExtraInfo = 0;
                        
INPUT input[2];
input[0].type = input[1].type = INPUT_KEYBOARD;
input[0].ki = keyDown;
input[1].ki = keyUp;

SendInput(2, input, sizeof(INPUT));



now these extra lines of code would not be a problem, but as luck would have it, i need to do this inside of a dll.

the dll uses shared memory, and all variables in shared memory MUST be instalized at declaration.

i can instalize keyDown and keyUp at their declarations, but run into problems when trying to instalize a array of structures at declaration.




>> can i get away with using keybd_event instead of SendInput, and what would the disadvantages be?

>> would it be advisable to put up with the large arrays instalized each time, for the advantages gained by using SendInput?

>> if so, can u see any way to instalize the array of structures at declaration? i tried pretending it was a multidimenional array but it didnt work?


cheers... suma
0
 
AlexFMCommented:
This is interesting C++ problem which deservs to be discussed in C++ forum. When I tried to initialize INPUT array by the following way:

INPUT input[2] =
{
    {INPUT_KEYBOARD, {VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY, 0, 0} },
    {INPUT_KEYBOARD, {VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY|KEYEVENTF_KEYUP, 0, 0} }
};

I found that it's values are wrong, because it is initialized according to first union member MOUSEINPUT (you can see this in the debugger). I don't know how to initialize it using second union type.
Of course, you can initialize it by the first type, so that second type will get required values, but this is worse than using keybd_event.
0
 
suma_dsAuthor Commented:
the dropdown list in my compiler indicates that the order of the variables is:

hi
ki
mi
type

so (correct me if im wrong) it should be:

INPUT input[2] =
{
    {{VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY, 0, 0}, INPUT_KEYBOARD},
    {{VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0, 0}, INPUT_KEYBOARD }
};

now this assigns {VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY, 0, 0} to "hi", and INPUT_KEYBOARD to "mi"

so if it was changed to:

INPUT input[2] =
{
    {0, {VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY, 0, 0}, 0, INPUT_KEYBOARD},
    {0, {VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0, 0}, 0, INPUT_KEYBOARD }
};

then the values should be assigned correctly.

the only remaining problem is whether this it is acceptable to assign 0 (zero) to "hi" and "mi".

what do u think??
0
 
suma_dsAuthor Commented:
damn... the compiler shows KEYBDINPUT as

dwExtraInfo
dwFlags
wScan
wVk

but msdn shows it as

    WORD wVk;
    WORD wScan;
    DWORD dwFlags;
    DWORD time;
    ULONG_PTR dwExtraInfo


which is correct?

btw im using visual studio .net
0
 
AlexFMCommented:
typedef struct tagINPUT {
  DWORD   type;
  union {
      MOUSEINPUT      mi;
      KEYBDINPUT      ki;
      HARDWAREINPUT   hi;
  };
} INPUT, *PINPUT;

typedef struct tagKEYBDINPUT {
  WORD      wVk;
  WORD      wScan;
  DWORD     dwFlags;
  DWORD     time;
  ULONG_PTR dwExtraInfo;
} KEYBDINPUT, *PKEYBDINPUT;

{INPUT_KEYBOARD, {VK_CAPITAL, 0, KEYEVENTF_EXTENDEDKEY, 0, 0} }

I want to get the following result:
type = INPUT_KEYBOARD
ki.wVk = VK_CAPITAL
ki.wScan = 0
ki.dwFlags = KEYEVENTF_EXTENDEDKEY
ki.time = 0
ki.dwExtraInfo = 0

But first union member is MOUSEINPUT mi:

typedef struct tagMOUSEINPUT {
  LONG    dx;
  LONG    dy;
  DWORD   mouseData;
  DWORD   dwFlags;
  DWORD   time;
  ULONG_PTR   dwExtraInfo;
} MOUSEINPUT, *PMOUSEINPUT;

so result of initialization is:

mi.dx = INPUT_KEYBOARD
mi.dy = VK_CAPITAL
mi.mouseData = 0
mi.dwFlags = KEYEVENTF_EXTENDEDKEY
mi.time = 0
mi.dwExtraInfo = 0

Since two structures have the same memory address, KEYBDINPUT ki is filled by wrong way. This is the problem. I don't know it's solution, ask in C++ area.
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

  • 4
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now