user1803300
user1803300

Reputation:

Determine if SHIFT is pressed insde keyboard Hook Proc

inside my hook proc, how can i determine whether a used is pressing SHIFT (without releasing it) and then a char key (like A) ?

for example, if i press Shift+A, i want to know that it will be an uppercase a instead of getting it like Shift, a

so it will be A, if a user presses and releases Shift, it will capture Shift only.

the instaleld hook is WH_KEYBOARD (Global)

function KeyHookProc(Code: Integer; wVirtKey: WPARAM; lKeyStroke: LPARAM)
  : LRESULT; stdcall;
type
  TTransitionState = (tsPressed, tsReleased);

  PKeystrokeData = ^TKeystrokeData;

  TKeystrokeData = record
    VirtualKey: WPARAM;
    KeyStroke: LPARAM;
    KeyState: TKeyboardState;
  end;
var
  Transition: TTransitionState;
  KeystrokeDataPtr: PKeystrokeData;
begin
  Result := CallNextHookEx(hKeyHook, Code, wVirtKey, lKeyStroke);

  Transition := TTransitionState((lKeyStroke shr 31) and 1);

  if (Code = HC_ACTION) and (Transition = tsPressed) then
  begin
    New(KeystrokeDataPtr);
    try
      KeystrokeDataPtr^.VirtualKey := wVirtKey;
      KeystrokeDataPtr^.KeyStroke := lKeyStroke;
      GetKeyboardState(KeystrokeDataPtr^.KeyState);
      SendMessage(hConsole, WM_NULL, 0, LPARAM(KeystrokeDataPtr));
    finally
      Dispose(KeystrokeDataPtr);
    end;
  end;
end;

Upvotes: 0

Views: 4977

Answers (2)

David Heffernan
David Heffernan

Reputation: 612914

You detect the pressing of the SHIFT key when your hook proc is called with wParam equal to VK_SHIFT.

When your hook proc is called corresponding to the A key being pressed, the wParam and lParam values are identical whether or not the SHIFT key is down. Since you are not calling TranslateMessage and DispatchMessage as would happen in a normal message loop, you are going to have to translate the raw key down/up events into actual key presses.

It's probably going to be easiest for you to use GetKeyState(VK_SHIFT)<0 to detect whether or not the SHIFT key is down. That depends on exactly what you are trying to do. It looks a little like you are making a fully functioned keylogger. In which case ad-hoc calls to GetKeyState(VK_SHIFT)<0 may not meet your needs, and proper processing of the individual key down/up messages would be better.


Some other comments:

  1. Why are you heap allocating your TKeystrokeData record? You can perfectly well use a stack allocated record.
  2. I hope that hConsole is a window in the same process as your hook. If not it won't receive any useful information because the pointer you send it is only meaningful in the process that defines it. If you want to send information cross-process them WM_COPYDATA is your guy.

Upvotes: 0

RobertFrank
RobertFrank

Reputation: 7394

Here's the code we use in normal day-to-day use to detect the shift key. I've never used it in a hooked context, so I don't know if it would work there, or if something is different in that context that would prevent it.

function ShiftIsDown : Boolean;
var
  State: TKeyboardState;
begin
  WINDOWS.GetKeyboardState(State);
  Result := ((State[vk_Shift] and 128) <> 0);
end; 

Upvotes: 4

Related Questions