Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "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
2-1139716245
stef
2006-02-12 06:50
2006.02.26
Работа с Excell в Delphi


15-1138722230
jack128
2006-01-31 18:43
2006.02.26
Сумашедший тест :-)


1-1138166366
DDDeN
2006-01-25 08:19
2006.02.26
Температура CPU


2-1139561720
ААА
2006-02-10 11:55
2006.02.26
Как написать движок.


9-1125765050
Hacker117
2005-09-03 20:30
2006.02.26
Экспорт моделей из Half-life 2 Lion





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский