Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2004.12.26;
Скачать: [xml.tar.bz2];

Вниз

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

 
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 вся ветка

Форум: "WinAPI";
Текущий архив: 2004.12.26;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.48 MB
Время: 0.056 c
1-1102587491
Aleks
2004-12-09 13:18
2004.12.26
как передать фокус и узнать код символа


1-1103046008
Arnold
2004-12-14 20:40
2004.12.26
Выравнивание по ширине


14-1102590544
DiamondShark
2004-12-09 14:09
2004.12.26
Радикальное решение.


3-1101817437
leha
2004-11-30 15:23
2004.12.26
dBase + ADO


1-1102530469
pkm
2004-12-08 21:27
2004.12.26
Скрытие окна.





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский