if GetAsyncKeyState(69) <> 0) then
begin
showmessage('нажата E');
end;
if GetAsyncKeyState(91) <> 0) then
begin
showmessage('нажата левая WIN');
end;
//все нормально, обрабатывается
//а на комбинацию не реагирует
if (GetAsyncKeyState(69) <> 0) and (GetAsyncKeyState(91) <> 0) then
begin
showmessage('WIN+E');
end;
отловить комбинацию WIN+E
помогите пожалуйста разобраться нужно отловить на своей форме, что нажата комбинация win+e, 91 - виртуальный код клавиши левой WIN, 69 - виртуальный код клавиши E
Я даже скажу больше, каким то чудом вот такой код тоже не работает:
Код:
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
var
KeyBuff: TKeyboardState;
begin
// if key = 69 then
// begin
FillChar(KeyBuff, SizeOf(KeyBuff), 0);
GetKeyboardState(KeyBuff);
if (KeyBuff[90] = 1) and (KeyBuff[68] = 1) then
begin
ShowMessage('O ya, baby');
end;
// end;
end;
Shift: TShiftState);
var
KeyBuff: TKeyboardState;
begin
// if key = 69 then
// begin
FillChar(KeyBuff, SizeOf(KeyBuff), 0);
GetKeyboardState(KeyBuff);
if (KeyBuff[90] = 1) and (KeyBuff[68] = 1) then
begin
ShowMessage('O ya, baby');
end;
// end;
end;
По ходу тут нужен какой то более суровый перехват
Не знаю как у вас на данный момент, но у меня не получилось добиться перехвата именно Win + E. Получилось E + Win .
Поэтому было принято решение поставить низкоуровневый хук клавиатуры(функция-фильтр):
Код:
function KeyboardProc(Code: INTEGER; WParam: INTEGER; LParam: INTEGER): INTEGER; stdcall;
begin
if Code < 0 then
begin
Result := CallNextHookEx(Hook, Code, WParam, LParam);
Exit;
end;
if WParam = WM_KEYUP then
begin
if (GetAsyncKeyState(69) <> 0) and (GetAsyncKeyState(91) <> 0) then
begin
// Обрабатываем нажатие тут
ShowMessage('O ya, baby');
end;
end;
Result := CallNextHookEx(Hook, Code, WParam, LParam);
end;
begin
if Code < 0 then
begin
Result := CallNextHookEx(Hook, Code, WParam, LParam);
Exit;
end;
if WParam = WM_KEYUP then
begin
if (GetAsyncKeyState(69) <> 0) and (GetAsyncKeyState(91) <> 0) then
begin
// Обрабатываем нажатие тут
ShowMessage('O ya, baby');
end;
end;
Result := CallNextHookEx(Hook, Code, WParam, LParam);
end;
Код:
Hook := SetWindowsHookEx(WH_KEYBOARD_LL, @KeyboardProc, Hinstance, 0);
Дело в том что хук срабатывает до изменения состояния клавиатуры. И если считывать по событию WM_KEYDOWN то окажется что клавиши ещё не нажаты.
Это как в фильме терминатор. Он ещё не был создан, но уже убивал джона конора :-)
В общем этому хуку по барабану в фокусе окно или нет. Если нажали Win + E и открылся проводник то и вы получите событие.
Здесь есть одна проблемка. В виду крайней простоты код реагирует и на E + Win .
Если задача не проворонить открытие проводника то этого достаточно.
Не забывайте снимать хук, когда закрывается программа или он больше не нужен.
Какая может быть разница программисту четное или нет. Если действительно понадобилось бери да считай.
В общем мне это показалось натуральной дурью.
RegisterHotkey подойдет для вашей задачи?
Можно
Спасибо за информацию. Один момент
в коде
Код:
Hook := SetWindowsHookEx(WH_KEYBOARD_LL, @KeyboardProc, Hinstance, 0);
И еще хотелось бы прояснить мне нужно если активна моя форма и нажато win+e перехватить его и заблокировать, возможно ли это сделать по человечески?
а не например в хуке искать по заголовку окна "Мой компьютер" и убивать его?
Такая же задача актуальна насчет WIN+R
Спасибо
Код:
const
WH_KEYBOARD_LL = 13;
WH_KEYBOARD_LL = 13;
Без _LL ставится другой хук. Там назначение WParam и LParam другое. Правильно что не работал.
Хотел спросить запрешать планируете или только отлов, зря не стал. Ладно подумаем.
Какая студия? Вы вообще под виндовс пишете, а то "Delphi & Kylix" очень информативно?
Вы бы сразу поставили задачу нормально. Я правильно понимаю? Вы не хотите чтоб нажатие WIN + E попало в процесс explorer. Если так то хук по любому, вопрос какой. По логике должен быть хук который вызывается после смены состояния клавиатуры, но до отправки сообщения об этом всем процессам. Вот в этот момент нужно получить состояние интересующих кнопок и если оно не устраивает сменить
Есть конечно другие варианты, по типу внедрения в explorer и предотвращение реакции от туда, но это тяжкие методы
Попробуйте вот такой код(функция-фильтр низкоуровневого хука):
Код:
function KeyboardProc(Code: INTEGER; WParam: INTEGER; LParam: INTEGER): INTEGER; stdcall;
var
KeyboardInfo: PLLKEYBOARDINFO;
begin
if Code < 0 then
begin
Result := CallNextHookEx(Hook, Code, WParam, LParam);
exit;
end;
if Code = HC_ACTION then
begin
case WParam of
WM_SYSKEYDOWN, WM_KEYDOWN:
begin
KeyboardInfo := PLLKEYBOARDINFO(LParam);
if (KeyboardInfo.vkCode = 69) and (GetAsyncKeyState(91) <> 0) then
begin
Result := 1;
exit;
end;
end;
end;
end;
Result := CallNextHookEx(Hook, Code, WParam, LParam);
end;
var
KeyboardInfo: PLLKEYBOARDINFO;
begin
if Code < 0 then
begin
Result := CallNextHookEx(Hook, Code, WParam, LParam);
exit;
end;
if Code = HC_ACTION then
begin
case WParam of
WM_SYSKEYDOWN, WM_KEYDOWN:
begin
KeyboardInfo := PLLKEYBOARDINFO(LParam);
if (KeyboardInfo.vkCode = 69) and (GetAsyncKeyState(91) <> 0) then
begin
Result := 1;
exit;
end;
end;
end;
end;
Result := CallNextHookEx(Hook, Code, WParam, LParam);
end;
Код:
type
PLLKEYBOARDINFO = ^TLLKEYBOARDINFO;
TLLKEYBOARDINFO = packed record
vkCode: CARDINAL;
scanCode: CARDINAL;
flags: CARDINAL;
time: CARDINAL;
dwExtraInfo: CARDINAL;
end;
PLLKEYBOARDINFO = ^TLLKEYBOARDINFO;
TLLKEYBOARDINFO = packed record
vkCode: CARDINAL;
scanCode: CARDINAL;
flags: CARDINAL;
time: CARDINAL;
dwExtraInfo: CARDINAL;
end;
В общем тут мы не допускаем их нажатия, поэтому их удержание в расчёте на появление проводника тоже не проканывает
А код в вопросе не решает таких задач. На момент когда ваша ппрограмма получает сообщение о нажатии этих клавиш предотвращать это событие уже поздно.
Спасибо! Все работает. Проверял на среде Delphi7
Скажи пожалуйста, а можно сделать так, чтобы при том коде, что указал ты выше не появлялось меню ПУСК при нажатии комбинации WIN+E? Спасибо.