olagutt
asked on
Catching keyboard with SetWindowsHookEx
Hi everybody,
I'm struggling a bit with SetWindowsHookEx, from win32.dll. At the current stage, I have developed a custom component that acts as a Progressbar, but I want this to respond to keystrokes, even when the component doesn't have the focus.
I.e. when a user hits the Esc button.
My solution to the problem seems to be to hook the keyboard and analyse everything that the user presses with SetWindowsHookEx.
I have included some functions for this inside my component, but every time I hit the keyboard, I get an access violation error. Does this mean that it's impossible to trap the keyboard with a component?? Should I put this code in a DLL instead? Or do you have some other suggestions?
Here's what it looks like :
function TProgressControl.SetupHook : boolean;
begin
CurrentHook:=SetWindowsHoo kEx(WH_KEY BOARD,
@TProgressControl.KeyBoard Hook,
0,
GetCurrentThreadID()
);
SetupHook := (CurrentHook <> 0);
end;
function TProgressControl.RemoveHoo k: boolean;
begin
RemoveHook:=UnhookWindowsH ookEx(Curr entHook);
end;
function TProgressControl.KeyBoardH ook(code: integer; wParam: word; lParam: longword): longword; stdcall;
begin
if code < 0 then
begin
KeyBoardHook:=CallNextHook Ex(Current Hook,code, wParam,lpa ram);
Exit;
end;
if Lo(wParam) = 27 then Stop //here I'm stopping my Progressbar
CallNextHookEx(CurrentHook ,code,wPar am,lparam) ;
KeyBoardHook:=0;
end;
Regards,
Ola
I'm struggling a bit with SetWindowsHookEx, from win32.dll. At the current stage, I have developed a custom component that acts as a Progressbar, but I want this to respond to keystrokes, even when the component doesn't have the focus.
I.e. when a user hits the Esc button.
My solution to the problem seems to be to hook the keyboard and analyse everything that the user presses with SetWindowsHookEx.
I have included some functions for this inside my component, but every time I hit the keyboard, I get an access violation error. Does this mean that it's impossible to trap the keyboard with a component?? Should I put this code in a DLL instead? Or do you have some other suggestions?
Here's what it looks like :
function TProgressControl.SetupHook
begin
CurrentHook:=SetWindowsHoo
@TProgressControl.KeyBoard
0,
GetCurrentThreadID()
);
SetupHook := (CurrentHook <> 0);
end;
function TProgressControl.RemoveHoo
begin
RemoveHook:=UnhookWindowsH
end;
function TProgressControl.KeyBoardH
begin
if code < 0 then
begin
KeyBoardHook:=CallNextHook
Exit;
end;
if Lo(wParam) = 27 then Stop //here I'm stopping my Progressbar
CallNextHookEx(CurrentHook
KeyBoardHook:=0;
end;
Regards,
Ola
Could be also used a hook inside your app, a journal hook...
To catch keys (like in a keylogger) you can use something like the code below, in a timer with interval set to 1 :
for i:=8 To 255 do
begin
if GetAsyncKeyState(i)=-32767 then
begin
case i of
8: pressed_key:='{UNDO}';
9: pressed_key:='{TAB}';
//etc.
end;
end;
To catch keys (like in a keylogger) you can use something like the code below, in a timer with interval set to 1 :
for i:=8 To 255 do
begin
if GetAsyncKeyState(i)=-32767
begin
case i of
8: pressed_key:='{UNDO}';
9: pressed_key:='{TAB}';
//etc.
end;
end;
ESC is a dialog key like Tab so you can only get it if your Progressbar is a TWinControl. See TWinControl.CNKeyDown implementation for ways to specifically tell the VCL that your control wants to handle ESC.
ASKER
First of all, I'm not talking about application focus, but component focus.
>>For catching ESC inside your app it is easier to simply use OnKeyDown.
OnKeyDown will only be triggered if the component has got the focus, so that will not help me much... :(
Are you saying that TwinControl is able to provide me with event triggers for the whole form? Regardless of component focus?
Your comments are highly appreciated :)
Ola
>>For catching ESC inside your app it is easier to simply use OnKeyDown.
OnKeyDown will only be triggered if the component has got the focus, so that will not help me much... :(
Are you saying that TwinControl is able to provide me with event triggers for the whole form? Regardless of component focus?
Your comments are highly appreciated :)
Ola
You are right, but you do not need a hook for that. There are several ways to get the messages. Try Application.HookMainMainWi ndow and catch WM_KEYDOWN param VK_ESC. Call back if it does not work.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
That did the trick!
I just needed to know how to access my objects when the hook-function was outside my component-class.
Slick812 gave the answer, so the points will go to him.
Roberts last tip was also interesting...maybe I'll look into that later...
Best regards,
Ola
I just needed to know how to access my objects when the hook-function was outside my component-class.
Slick812 gave the answer, so the points will go to him.
Roberts last tip was also interesting...maybe I'll look into that later...
Best regards,
Ola
BTW your idea is silly. It is against all user interface conventions.
ALL keyboard input goes to the application which has the focus. So when i want to legitimately enter ESC in another app your progress will act upon it. This will infuriate any user.
For catching ESC inside your app it is easier to simply use OnKeyDown.