Форум: "WinAPI";
Текущий архив: 2006.02.26;
Скачать: [xml.tar.bz2];
ВнизКак правильно обработать WH_KEYBOARD? Найти похожие ветки
← →
kami © (2005-12-04 14:59) [0]Все поиски в интернете привели к нахождению нескольких примеров. Одни из них даже не компилировались, другие - определяли все нажатые клавиши, как заглавные английские.
Пришлось порыться в MSDN и написать такой вот код:var
MyHook:HHook;
KeyFile:TFileStream;
function KeyboardProcLL(code: integer; W: WParam; L: LParam): LResult;
var
kbd:KBDLLHOOKSTRUCT;
keyState:TKeyboardState;
p:PChar;
RetChars:integer;
ProcessID:DWORD;
begin
if code<0 then
begin
Result:=CallNextHookEx(MyHook,code,W,L);
Exit;
end;
if (W=WM_KEYUP) then
begin
kbd:=KBDLLHOOKSTRUCT(Pointer(L)^); // получили структуру KBDLLHOOKSTRUCT
GetKeyboardState(KeyState);
GetMem(p,3);
ProcessID:=1;// без узнавания активного потока почему-то не работает
RetChars:=ToASCIIEx( // если использовать просто vkCode, то выдает заглавные английские буквы
kbd.vkCode,
kbd.scanCode,
keyState,
p,
0,
GetKeyboardLayout(GetWindowThreadProcessId(GetForegroundWindow,@ProcessID)));
// в p - нажатые символы kbd - не изменялся
if RetChars>0 then
KeyFile.WriteBuffer(p[0],RetChars);
FreeMem(p);
end;
Result:=CallNextHookEx(MyHook,code,W,L);
end;
Но он неправильно обрабатывает нажатия символов на цифровых клавишах (типа" № # % ?
) :(
В общем, что-то я опять перенамудрил :(
Как все-таки правильно получить нажатый символ (с учетом раскладки клавиатуры для активного потока) ?
← →
kami © (2005-12-04 18:27) [1]Неужели никто не знает? Не может быть, чтобы нельзя было сделать, PuntoSwitcher прекрасно с этим справляется
Up, в смысле :)
← →
kami © (2005-12-06 22:03) [2]Up еще раз :)
← →
KADAN © (2005-12-07 07:58) [3]> другие - определяли все нажатые клавиши, как заглавные английские.
а я всю жизнь думал что ловится код клавиши а не символ... а пунтосвитчер просто клавиатуру "выучил" и следит за состоянием всяческих "шифтов", капсов и раскладкой
← →
kami © (2005-12-07 16:43) [4]KADAN © (07.12.05 7:58) [3]
а пунтосвитчер просто клавиатуру "выучил"
На чем основывается это утверждение?
ловится код клавиши
Вообще-то ловится (вернее, посылается в процедуру хука) виртуальный код клавиши и её hardware скан-код (основные параметры KBDLLHOOKSTRUCT). Вот я и хочу узнать, как из них определить, какой символ отобразится в программе. Мой вариант кода работает некорректно на цифровых клавишах, а заводить полную таблицу раскладки клавиатуры во всех режимах, с учетом нажатых шифтов, капслоков и иже с ними, имхо, совсем неверное решение.
← →
Lamer@fools.ua © (2005-12-07 20:50) [5]Функция MapVirtualKey/MapVirtualKeyEx не спасёт отца русской демократии?
← →
kami © (2005-12-07 21:40) [6]Lamer@fools.ua © (07.12.05 20:50) [5]
MapVirtualKeyEx
Пока она меня не спасает :)
Пытался ее использовать с самого начала, сейчас попробовал еще раз - возвращает только заглавные английские буквы, и в MSDN написано : uCode is a virtual-key code and is translated into an unshifted character value (пробовал использовать ее с параметром 2 (VCode>Char)).
Может, что-то я не так делаю?
← →
Lamer@fools.ua © (2005-12-07 22:18) [7]>>kami ©
В тестовом приложении без хуков всё отлично работает (и текущая раскладка учитывается и состояние Shift и Caps Lock):procedure TForm1.Timer1Timer(Sender: TObject);
var
KS: TKeyboardState;
I: Low(KS) .. High(KS);
S: String;
C: UINT;
C1: Integer;
Ch: packed array [0 .. 1] of Char;
begin
if not GetKeyboardState(KS) then
RaiseLastOSError;
Memo1.Lines.BeginUpdate;
try
Memo1.Lines.Clear;
for I := Low(KS) to High(KS) do
begin
if KS[I] and $80 <> 0 then
begin
S := Format("%.2xh", [I]);
C := MapVirtualKey(I, 2);
if C <> 0 then
S := S + Format(": ""%s""", [Char(C)])
else
S := S + ": ?";
C := MapVirtualKey(I, 0);
if C <> 0 then
begin
C1 := ToAscii(I, C, KS, Ch, 0);
case C1 of
1: S := S + Format(": ""%s"" -- #%d", [Ch[0], Byte(Ch[0])]);
2: S := S + Format(": ""%s%s"" -- #%d#%d", [Ch[0], Ch[1], Byte(Ch[0]), Byte(Ch[1])]);
else
S := S + ": ?";
end;
end;
Memo1.Lines.Add(S);
end;
end;
finally
Memo1.Lines.EndUpdate;
end;
end;
На форме:Memo1: TMemo;
Timer1: TTimer;
У таймера Interval = 100.
← →
kami © (2005-12-07 22:48) [8]Lamer@fools.ua © (07.12.05 22:18) [7]
Посмотрел, в принципе - то же самое: получение vkCode и ScanCode, затем - преобразование в ASCII.
Перенес в хук - точно такая же картина (только, ко всему прочему, определяет все нажатия клавиш в раскладке моего приложения. Оно и понятно - ToASCII работает с раскладкой своего потока ).
В своем приложении, к стати,определяет все правильно, а вот с другими :(
← →
kami © (2005-12-07 23:27) [9]Lamer@fools.ua © (07.12.05 22:18)
Сейчас поекспериментил, выяснил, что в чужом приложении не определяются нажатия шифтов из моего хука.
Посему вставил следующую строчку :GetKeyboardState(KeyState);
KeyState[VK_SHIFT]:=GetKeyState(VK_SHIFT);
Вроде, все заработало.
Спасибо.
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2006.02.26;
Скачать: [xml.tar.bz2];
Память: 0.47 MB
Время: 0.479 c