在我的钩子proc中,如何判断一个是否按下了SHIFT(不释放它)然后是一个char键(如A)?
例如,如果我按Shift + A,我想知道它将是一个大写的,而不是像Shift一样,
所以它将是A,如果用户按下并释放Shift,它将仅捕获Shift。
instaleld钩子是WH_KEYBOARD(全局)
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;
答案 0 :(得分:3)
以下是我们在正常日常使用中检测换档键的代码。我从来没有在钩子上下文中使用它,所以我不知道它是否会在那里工作,或者在那种情况下会有什么不同会阻止它。
function ShiftIsDown : Boolean;
var
State: TKeyboardState;
begin
WINDOWS.GetKeyboardState(State);
Result := ((State[vk_Shift] and 128) <> 0);
end;
答案 1 :(得分:0)
当您使用wParam
等于VK_SHIFT
调用钩子proc时,您会检测到按下 SHIFT 键。
当按下 A 键对应的钩子proc时,无论 SHIFT wParam和lParam
值都是相同的>关键是关闭。由于您没有像在正常的消息循环中那样调用TranslateMessage
和DispatchMessage
,因此您必须将原始键向下/向上事件转换为实际的按键操作。
使用GetKeyState(VK_SHIFT)<0
来检测 SHIFT 键是否关闭可能最容易。这取决于你想要做什么。它看起来有点像你正在制作一个功能齐全的键盘记录器。在这种情况下,对GetKeyState(VK_SHIFT)<0
的临时呼叫可能无法满足您的需求,并且正确处理单个按键向下/向上消息会更好。
其他一些评论:
TKeystrokeData
记录?你可以很好地使用堆栈分配记录。hConsole
是一个与你的钩子在同一个过程中的窗口。如果不是,它将不会收到任何有用的信息,因为您发送它的指针仅在定义它的过程中有意义。如果您想发送信息,那么他们就是WM_COPYDATA
。