AuthorwareXtras
asked on
Disable the numlock key using Delphi 7
I want to be able to use Delphi 7 to disable the numlock key. This needs to work in XP and preferably Vista also.
Actually what I specifically want to do is to make sure the numlock key can't be turned off if that makes more sense? setting it explicitly to on first, before turning off the key would therefore work well.
Actually what I specifically want to do is to make sure the numlock key can't be turned off if that makes more sense? setting it explicitly to on first, before turning off the key would therefore work well.
This should be everything you need:
1. Method to set NumLock state
2. Keyboard hook to allow watching for attempts to change the NumLock state and reset it if needed.
-Lee
1. Method to set NumLock state
2. Keyboard hook to allow watching for attempts to change the NumLock state and reset it if needed.
-Lee
var
KbdHook : HHook;
//call initially to set numlock on
procedure SetNumLock(Lock : Boolean);
var
KeyState : TKeyboardState;
begin
GetKeyboardState(KeyState);
if Lock and (KeyState[VK_NUMLOCK] = 0) then begin
//simulate key presses
Keybd_Event(VK_NUMLOCK, 1, KEYEVENTF_EXTENDEDKEY, 0);
Keybd_Event(VK_NUMLOCK, 1, KEYEVENTF_EXTENDEDKEY or KEYEVENTF_KEYUP, 0);
end else if not Lock and (KeyState[VK_NUMLOCK] = 1) then begin
//simulate key presses
Keybd_Event(VK_NUMLOCK, 0, KEYEVENTF_EXTENDEDKEY, 0);
Keybd_Event(VK_NUMLOCK, 0, KEYEVENTF_EXTENDEDKEY or KEYEVENTF_KEYUP, 0);
end;
end;
function KeyboardHookProc(nCode : Integer; wParam : Word; lParam : LongInt) : LongInt;
stdcall;
begin
if nCode < 0 then begin
//If code is less than zero, the hook procedure must pass the message to
//the CallNextHookEx function without further processing and should
//return the value returned by CallNextHookEx
Result := CallNextHookEx(KbdHook, nCode, wParam, lParam);
Exit;
end;
if (wParam = VK_NUMLOCK) then begin
Result := 0; //stop further processing
SetNumLock(True); //re-set numlock
end else
Result := CallNextHookEx(KbdHook, nCode, wParam, lParam);
end;
//do this either in form create/destroy or somewhere similar.
procedure TForm1.FormCreate(Sender : TObject);
begin
//Set the keyboard hook so we can intercept keyboard input
KbdHook := SetWindowsHookEx(WH_KEYBOARD, @KeyboardHookProc, HInstance,
GetCurrentThreadId());
end;
procedure TForm1.FormDestroy(Sender : TObject);
begin
//unhook
UnHookWindowsHookEx(KbdHook);
end;
ASKER
Does this not have to be done from a DLL so the hook is system wide?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
In a Delphi app it works fine.
In a DLL, when I press the numlock key, the numlock indicator flashes on and off repeatedly and the whole machine slows down?
In a DLL, when I press the numlock key, the numlock indicator flashes on and off repeatedly and the whole machine slows down?
ASKER
When I change this line:
Result := 0; //stop further processing
to a non zero value (e.g. Result := 1;)
Then it functions.
Result := 0; //stop further processing
to a non zero value (e.g. Result := 1;)
Then it functions.
My mistake. You are correct - a non zero result should be returned from the keyboard hook to stop further processing.
keybd_event(VK_NUMLOCK, 0, 0, 0);
Actually the above will "hold down" the key.
To click try;
keybd_event(VK_NUMLOCK, 0, KEYEVENTF_KEYDOWN, 0);
To reverse it, try;
keybd_event(VK_NUMLOCK, 0, KEYEVENTF_KEYUP, 0);
John