![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Узнать активный элемент окна, имея хендл окна [D7, WinXP]
Lezha © (2006-08-16 17:42:00)Здравствуйте, написал хук, который перехватывает нажатие стрл+ээ и должен заменять его апостроф. Проблема в том, что я не могу узнать дескриптор елемента ввода, который имеет фокус.
SendMessage(GetFocus, WM_CHAR, Ord(''''),1); -- не работает.
При передаче Application.MainForm.ActiveMDIChild.ActiveControl.Handle апостроф отсылается не туда, если текст вводится в модальном диалоговом окне.
Lezha (2006-08-18 14:24:00) [1]GrayFace, все-таки, на вижу смысла менять хук, если он правильно вызывается и работает в таком виде :)
К сожалению, функции keybd_message нигде не нашел, нашел только keybd_event, но она также передает "э" вместо апострофа:
keybd_event(Key_Apostrophe, 222, 0, 0); или
keybd_event(Key_Apostrophe, 39, 0, 0);
SendMessage(PEventMsg(lParam)^.hwnd, WM_CHAR, 222, 1); или
SendMessage(PEventMsg(lParam)^.hwnd, WM_CHAR, 39, 1);
также отсылают "э".
К сожалению, решение проблемы вижу только в переключении раскладки, но вот как вернуть ее назад... :(
GrayFace (2006-08-17 19:53:00) [2]А зачем тут менять раскладку?
Еще можно использовать keybd_message. И можно без хука.
Lezha (17.08.06 11:59) [7]
Да, хук локальный, но с хуком все ок -- он работает правильно.
А вот и нет.
Lezha (17.08.06 11:59) [7]
function KeyBoardHook(code: integer; wParam: word; lParam: longword): longword; stdcall;
Надо function KeyBoardHook(code: integer; wParam, lParam: longint): longint; stdcall;
Lezha (17.08.06 13:55) [16]
Просто я не нашел SetAsyncKeyState() :)
Есть еще GetKeyState.
Lezha (2006-08-17 14:07:00) [3]CallNextHookEx(CurrentHook,code,wParam,lparam); //call the next hook proc if there is one
KeyBoardHook:=0; //if KeyBoardHook returns a non-zero value, the window that should get
//the keyboard message doesnt get it.
if Status=2 then
begin
LoadKeyboardLayout( StrCopy(Layout,'00000419'),KLF_ACTIVATE);
Status := 0;
end;
Это я ставил в конце хука. Раскладка сначала возвращается, а потом уже сообщение передается.
Ketmar (2006-08-17 13:58:00) [4]> [16] Lezha (17.08.06 13:55)
почему нельзя? кто запрещает старую запомнить?
Lezha (2006-08-17 13:55:00) [5]Просто я не нашел SetAsyncKeyState() :)
По теме: переключал раскладку: LoadKeyboardLayout(StrCopy(Layout,'00000409'),KLF_ACTIVATE);
Но назад-то ее нельзя вернуть. Может есть еще решения?
Ketmar (2006-08-17 13:52:00) [6]в смысле -- рузкльтаты могут отличаться.
Ketmar (2006-08-17 13:52:00) [7]> [13] Lezha (17.08.06 13:47)
странная логика -- перемешивать GetAsyncKeyState() и GetKeyboardState()... они могут и отличаться, между прочим. %-)
Lezha (2006-08-17 13:47:00) [8]:)) Блин, точно, стормозил.
Сейчас-то оно работает, но с раскладкой проблемма. То есть на стрл+ээ оно отсылает символ "э". Ведь оно ловит сканкоды клавиш, которые от раскладки на зависят, то есть я вроде не могу отослать апостроф без сендМесиджа? :(
function KeyBoardHook(code: integer; wParam: word; lParam: longword): longword; stdcall;
var KeyState : TKeyboardState;
begin
if code<0 then begin
KeyBoardHook:=CallNextHookEx(CurrentHook,code,wParam,lparam);
Exit;
end;
if (PEventMsg(lParam)^.paramH=222)and(GetAsyncKeyState(VK_CONTROL)<>0)then
begin
Inc(Status);
if Status=2 then
begin
GetKeyboardState(KeyState);
KeyState[VK_CONTROL] := not KeyState[VK_CONTROL];
SetKeyboardState(KeyState);
Status := 0;
end;
end;// else Status := 0;
CallNextHookEx(CurrentHook,code,wParam,lparam);
KeyBoardHook:=0;
end;
Ketmar (2006-08-17 13:05:00) [9]> [11] Lezha (17.08.06 12:56)
выводи полученое в memo, например. посмотри, что выведется после соответствующих нажатий. %-)
Lezha (2006-08-17 12:56:00) [10]Спасибо, пробую, только вот не могу найти, как мне определить коды при нажатии стрл+ээ. Дебаггом не получается -- даже активизировать окно не могу, брейкпоинт прерывает выполнение.
begin...end (2006-08-17 12:07:00) [11]> Lezha (17.08.06 11:59) [7]
> Изначально я хотел в хуке поджменить коды клавиш, но ничего
> не получилось.
И не получится. А вот если поставить хук WH_GETMESSAGE, то параметры сообщений (в том числе, и WM_KEYDOWN/WN_KEYUP/WM_CHAR) изменять будет можно. Может быть, так и поступить?
Ketmar (2006-08-17 12:06:00) [12]в хуке коды не подменяются. для этого ставь хук на GetMessage() и меняй параметры сообщения.
Lezha (2006-08-17 12:05:00) [13]PostMessage тоже не работает (пробовал WM_CHAR, WM_KEYDOWN, отсылал как Ord(''''), так и VK_TAB).
Lezha (2006-08-17 11:59:00) [14]Да, хук локальный, но с хуком все ок -- он работает правильно. Изначально я хотел в хуке поджменить коды клавиш, но ничего не получилось. Хук на сообщение WH_KEYBOARD.
function KeyBoardHook(code: integer; wParam: word; lParam: longword): longword; stdcall;
var Input: TInput;
begin
if code<0 then begin //if code is <0 your keyboard hook should always run CallNextHookEx instantly and
KeyBoardHook:=CallNextHookEx(CurrentHook,code,wParam,lparam); //then return the value from it.
Exit;
end;
// if (lParam and KF_UP)=0 then sysutils.beep; //if the key is being pressed, not releases, BEEP!
if (wParam = 222)and(HiWord(GetAsyncKeyState(VK_CONTROL))<>0) then
begin
Inc(Status);
if Status=4 then
begin
beep;
Status := 0;
with PKbDllHookStruct(lParam)^ do
begin
FillChar(Input,SizeOf(Input),0);
Input.Itype:=INPUT_KEYBOARD;
Input.ki.wVk:=Key_Apostrophe;
Input.ki.dwFlags:=0;
// SendInput(1,Input,SizeOf(Input));
SendMessage(Application.MainForm.ActiveMDIChild.ActiveControl.Handle, WM_CHAR, Ord(''''),1);
end;
Result := 1;
Exit;
end;
end else Status := 0;
CallNextHookEx(CurrentHook,code,wParam,lparam); //call the next hook proc if there is one
KeyBoardHook:=0;
end;
Ketmar (2006-08-17 11:57:00) [15]> [4] Lezha (17.08.06 11:46)
PostMessage(). потому что так правильно. %-)
begin...end (2006-08-17 11:53:00) [16]> Lezha (17.08.06 11:46) [4]
> А что значит посылать асинхронно?
Через PostMessage, например. Но моё замечание относилось только к посылке WM_KEYDOWN/WM_KEYUP, а не WM_CHAR.
А хук только в пределах потока Вашего приложения устанавливается? И какой?
Lezha (2006-08-17 11:46:00) [17]WM_KEYUP -- это для примера. Я пробовал в трех вариантах: WM_KEYUPб WM_KEYDOWN и WM_CHAR, пробовал и код символа, и вирт. код (VK_TAB, VK_SPACE) -- ничего не работает.
Кстати, мемо -- объект класса TDBMemo.
А что значит посылать асинхронно? Асинхронно чему? Извините, если вопрос глупый... :)
begin...end (2006-08-17 11:00:00) [18]И если уж посылать WM_KEYUP, то асинхронно.
Ketmar (2006-08-16 21:54:00) [19]а с какого испугу WM_KEYUP должно так работать? так VK_xxx посылать надо, а не код символа.
Lezha (2006-08-16 17:55:00) [20]Хм, может проблема вообще в другом? Не работает:
SendMessage(memo.Handle, WM_KEYUP, Ord(''''),1);