Модераторы: feodorv, GremlinProg, xvr, Fixin

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Key hook, перехват нажатия клавиш, Без использования dll, как сделать? 
:(
    Опции темы
ReFleX
Дата 30.10.2006, 19:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 499
Регистрация: 26.9.2004
Где: Таллинн

Репутация: нет
Всего: 3



Добрый день!

Рылся по форуму, но везде из подобных найденных тем в примерах используется библиотека которая отслеживает хук.

Из кучи примеров у меня получилось собрать именно тот который мне нужен:

DLL:
Код

#include <windows.h>
#include <iostream>

#ifdef __cplusplus
extern "C" {
#endif

HHOOK hHKeyBrd = NULL;

LRESULT CALLBACK KeyBrdProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    if (nCode >= 0){
        MessageBox(NULL,"Hook","Information",MB_OK);
    }
    return CallNextHookEx (hHKeyBrd,nCode,wParam,lParam);
}

__declspec(dllexport) bool SetHooks(HINSTANCE hModule)
{
    hHKeyBrd = SetWindowsHookEx(WH_KEYBOARD, KeyBrdProc, (HINSTANCE) hModule, NULL);
    return true; 
}

__declspec(dllexport) bool UnHook()
{
    return true;
}

#ifdef __cplusplus
}
#endif


EXE
Код

#include <windows.h>
#include <iostream>
#include <tchar.h>

HHOOK hH;

typedef bool(*dllProc)(HINSTANCE);

int _tmain(int argc, _TCHAR* argv[])
{    
    HINSTANCE hDll;
    dllProc prAddr;

    char *DllFile = "HookDll.dll";

    HINSTANCE  hModule = GetModuleHandle(DllFile);
    if ((hDll = LoadLibrary(DllFile))!=NULL){
        prAddr = (dllProc)GetProcAddress(hDll,"SetHooks");
    }else{
        printf("Can't load DLL");
        Sleep(3000);
        return 0;
    }
    (prAddr)(hDll);
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return 0;
}


Вопрос остаётся тот же, возможно ли объеденить DLL вместе с EXE?
Просто не очень хочеться тоскать библиотеку, пускай лучше EXE будет немного больше.

Я слышал, что microsoft позволяет работать с Hook как в DLL так и для EXE, но примера я нигде не нашёл, решил обратиться с помощью на любимый форум. smile 
PM WWW   Вверх
SergeCpp
Дата 30.10.2006, 19:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


 
**


Профиль
Группа: Участник
Сообщений: 955
Регистрация: 8.8.2005
Где: At Home

Репутация: 10
Всего: 124



Попробуйте вот так

char* DllFile = "HookExe.exe"; // и перенесите все функции в EXE

PM MAIL WWW ICQ   Вверх
ReFleX
Дата 30.10.2006, 19:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 499
Регистрация: 26.9.2004
Где: Таллинн

Репутация: нет
Всего: 3



Не думаю что это будет правильно... smile 
PM WWW   Вверх
anwe
Дата 30.10.2006, 20:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 748
Регистрация: 2.9.2006

Репутация: 1
Всего: 23



А такой хук не всегда требует нахождения функции-фильтра в отдельной длл-ке. Можно устанавливать и в своем приложении. Только и ловится будут свои сообщения.
PM MAIL   Вверх
ReFleX
Дата 30.10.2006, 20:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 499
Регистрация: 26.9.2004
Где: Таллинн

Репутация: нет
Всего: 3



Мне надо чтобы ловились нажатия клавиш вне программы, этого я добился, но так же нужно чтобы библиотеки небыло, чтобы не таскаться с ней.
PM WWW   Вверх
anwe
Дата 30.10.2006, 21:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 748
Регистрация: 2.9.2006

Репутация: 1
Всего: 23



Все системные хуки и хуки для потоков в другом приложении должны находиться в DLL.
PM MAIL   Вверх
Dude03
Дата 31.10.2006, 02:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 257
Регистрация: 28.4.2006

Репутация: 1
Всего: 6



Цитата(ReFleX @  30.10.2006,  20:34 Найти цитируемый пост)
Мне надо чтобы ловились нажатия клавиш вне программы, этого я добился, но так же нужно чтобы библиотеки небыло, чтобы не таскаться с ней. 

А в чем проблема?=) Почему нельзя загружать либу из ресурсов приложения.
Пусть тебя не смущает асм-код. Просто посмотри какие надо юзать функции(их имена после invoke):
Код

invoke FindResource, NULL, ADDR mres, RT_RCDATA
test eax, eax
je WMDESTROY
mov [hRes], eax
invoke SizeofResource, [hInstance], eax
mov [SizeRes], eax
invoke LoadResource, NULL, [hRes]
invoke LockResource, eax

PM MAIL   Вверх
ReFleX
Дата 31.10.2006, 02:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 499
Регистрация: 26.9.2004
Где: Таллинн

Репутация: нет
Всего: 3



Т.е. если я правильно понял, включить dll в приложение а после уже при открытие EXE работать с включённой библиотекой.


Цитата(Dude03 @  31.10.2006,  02:01 Найти цитируемый пост)
Пусть тебя не смущает асм-код.
тут с WinAPI голову сломаешь, а тут ещё и ассемблер smile  smile  smile 

PM WWW   Вверх
Earnest
Дата 31.10.2006, 08:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 33
Всего: 183



Эта DLL, содержащаю хук, должна подгружаться во все процессы, в которых будет выполняться код, так что
anwe прав: только локальные хуки можно ставить, используя процедуру, которая находится в EXE.
Цитата(MSDN)

The global hooks are a shared resource, and installing one affects all applications in the same desktop as the calling thread. All global hook functions must be in libraries. 



--------------------
...
PM   Вверх
SergeCpp
Дата 31.10.2006, 08:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


 
**


Профиль
Группа: Участник
Сообщений: 955
Регистрация: 8.8.2005
Где: At Home

Репутация: 10
Всего: 124



Код
BOOL WINAPI DllMain(
  HINSTANCE hinstDLL,
  DWORD fdwReason,
  LPVOID lpvReserved
);

int WinMain(
    HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow
);


Остаётся лишь распознать вызов LoadLibrary (по третьему параметру) и подкорректировать стек.

Не так велики ухищрения. Сделать можно.

Естественно, Entry Point должна быть своя — не та, что берётся из CRT0.C и CRTDLL.C, например (имена файлов VC).

PM MAIL WWW ICQ   Вверх
ReFleX
Дата 31.10.2006, 11:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 499
Регистрация: 26.9.2004
Где: Таллинн

Репутация: нет
Всего: 3



Цитата(SergeCpp @  31.10.2006,  08:42 Найти цитируемый пост)
Не так велики ухищрения. Сделать можно

 smile А можешь пример сделать, я просто в WinAPI не совсем хорошо разбираюсь. Так с лёту догнать написанное не могу.
PM WWW   Вверх
v2v
Дата 6.11.2006, 18:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1620
Регистрация: 20.9.2006
Где: Киев

Репутация: нет
Всего: 56



Вероятно это уже не актуально, но я хотел бы поделиться своими изыскаиями в области перехвата нажатия кнопки клавиатуры.
Не обязательно создавать длл для перехвата нажатий в текущем окне, но вот если вы хотите перехватывать нажатия из других окон...
единственный выход - это длл.
Если кому то интересно, могу выложитькод, где я перехватываю нажатия выполненные в этом окне



--------------------
PM   Вверх
Yra
Дата 30.12.2006, 14:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 115
Регистрация: 12.9.2006
Где: Украина, Киев

Репутация: нет
Всего: нет



v2v,  Выкладывай!!!! Или если не трудно - на мыло мне скинь пожалуйста : [email protected]
 smile 
PM MAIL   Вверх
jonie
Дата 3.1.2007, 01:44 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 7
Всего: 118



погавариват что есть еще и хуки низкого уровня... и они не требуют типа без длл. Я честно маловерю) хотите - проверяйте) да и на делфях)...
Код

 LT> Установка системных WH_KEYBOARD_LL и WH_MOUSE_LL, т.е. хуков низкого 
 LT> уровня, не требуют библиотеки. 
 DVS> жаль только Delphi о них понятия не имеет. 


const 
  WH_KEYBOARD_LL = 13; 
  WH_MOUSE_LL = 14; 


  LLKHF_EXTENDED = KF_EXTENDED shr 8; 
  LLKHF_INJECTED = $00000010; 
  LLKHF_ALTDOWN = KF_ALTDOWN shr 8; 
  LLKHF_UP = KF_UP shr 8; 


  LLMHF_INJECTED = $00000001; 


{ Structure used by WH_KEYBOARD_LL } 
type 
  tagKBDLLHOOKSTRUCT  = packed record 
    vkCode : DWord; 
    scanCode : DWord; 
    flags : DWord; 
    time : DWord; 
    dwExtraInfo : PDWord; 
  end; 
  TKBDLLHOOKSTRUCT = tagKBDLLHOOKSTRUCT; 
  PKBDLLHOOKSTRUCT = ^TKBDLLHOOKSTRUCT; 


{ Structure used by WH_MOUSE_LL } 
  tagMSLLHOOKSTRUCT = packed record 
    pt : TPoint; 
    mouseData : DWord; 
    flags : DWord; 
    time : DWord; 
    dwExtraInfo : PDWord; 
  end; 
  tMSLLHOOKSTRUCT = tagMSLLHOOKSTRUCT; 
  PMSLLHOOKSTRUCT = ^TMSLLHOOKSTRUCT; 


  Вот, например, что когда-то предлагал Джеф Рихтер для 
  отключения любимых номеров (в вольном переводе): 


function  LowLevelKeyboardProc(nCode :Longint; awParam: WParam; alParam: 
LParam): DWord; stdcall; 
var 
  fEatKeystroke: Boolean; 
  p: PKBDLLHOOKSTRUCT; 
  buf: array [0..255] of Char; 
  sc: UINT; 
begin 
   fEatKeystroke := False; 


   if (nCode = HC_ACTION) then 
      case (awParam) of 
       WM_KEYDOWN, WM_SYSKEYDOWN, 
       WM_KEYUP, WM_SYSKEYUP: 
         begin 
          p := PKBDLLHOOKSTRUCT(alParam); 
          fEatKeystroke := 
            ((p.vkCode = VK_TAB) and (p.flags and LLKHF_ALTDOWN <> 0)) or 
            ((p.vkCode = VK_ESCAPE) and ((p.flags and LLKHF_ALTDOWN) <> 0)) or 
            ((p.vkCode = VK_ESCAPE) and ((GetKeyState(VK_CONTROL) and $8000) 
<>0)); 
         end; 
       end; 


   if fEatKeystroke then 
     Result := 1 
   else 
     Result := CallNextHookEx(0, nCode, awParam, alParam); 
end; 


var 
  hhk: HHOOK; 


procedure TForm1.Button1Click(Sender: TObject); 
begin 
  hhk:= SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, Hinstance, 0); 
end; 


procedure TForm1.Button2Click(Sender: TObject); 
begin 
  UnHookWindowsHookEx(hhk); 
end; 

а вообще можно и поэксперементировать с Dll-Exe-шкой)) SergeCpp писал...


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
W4FhLF
Дата 3.1.2007, 08:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


found myself
****


Профиль
Группа: Участник Клуба
Сообщений: 2831
Регистрация: 2.12.2006

Репутация: 12
Всего: 121



Цитата

погавариват что есть еще и хуки низкого уровня... и они не требуют типа без длл. 


Подмена адресов в SDT чтоли?


Как бы там ни было, вы должны понять, что когда устанавливается хук в чужом адресном пространстве должен находится Ваш модуль. Dll можно легко подгрузить в чужое адресное пространство, там все смещения вычисляются с учётом поправок(reloc), т.е. базовый адрес dll в адресном пространстве процесса может быть динамическим. А вот подгрузить Exe уже не так просто, нужно учесть кучу тонкостей PE формата, мне даже лень перечислять все. А сделать так, чтобы твой exe работал параллельно с основным в одном процессе вообще гиблая идея.

Это сообщение отредактировал(а) W4FhLF - 3.1.2007, 08:52


--------------------
"Бог умер" © Ницше
"Ницше умер" © Бог
PM ICQ   Вверх
kapbepucm
Дата 28.8.2007, 09:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 993
Регистрация: 14.6.2007
Где: Латвия

Репутация: нет
Всего: 12



Проблема из этой области. Вызываю дочерний процесс. Надо в дочке на все потоки повесить клавиатурый Hook. На не большое время. Таких действий будет несколько (дочек много). Можно ли обойтись без dll? И как в этом случае корректно вызвать SetWindowsHookExA?

Это сообщение отредактировал(а) kapbepucm - 28.8.2007, 09:56


--------------------
(С) kapbepucm
PM MAIL Skype   Вверх
jonie
Дата 28.8.2007, 23:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 7
Всего: 118



есть низкоуровневые хуки , они работают без длл-ок (но мне это не нравится лично)..
Цитата

И как в этом случае корректно вызвать SetWindowsHookExA?
?всмысле чтобы "не поставить дважды" чтоли?

P.S. возможно стоит пересмотреть архитектуру приложения и "включать" хук перед вызовом "дочек" и выключать при необходимости и уведомлять их о  сообщениях.. (я прост не вижу смысла дублировать код в "дочках" если их не одна)....


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
kapbepucm
Дата 29.8.2007, 08:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 993
Регистрация: 14.6.2007
Где: Латвия

Репутация: нет
Всего: 12



Ну, например, есть запущенных несколько дочек, и я хочу увидеть, что было нажато у конкретной дочке. Если использую WH_JOURNALRECORD, то получается в exe'шнике всё реализовать, правда Hook получается поставить на всю систему. Мне бы на конкретный процесс и только на клаву.

Это сообщение отредактировал(а) kapbepucm - 29.8.2007, 08:38


--------------------
(С) kapbepucm
PM MAIL Skype   Вверх
jonie
Дата 29.8.2007, 08:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 7
Всего: 118



хм... но ведь это ХУК глобальный, а не отправка уведомлений о нажатии клавиш процесса N родителю. Зачем хук тогда ?
Для конкретной и делай конкретно.... т.е. просто отсылай уведомления головному процессу о нажатии клавиши в дочке.
Зачем хук?


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
kapbepucm
Дата 29.8.2007, 08:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 993
Регистрация: 14.6.2007
Где: Латвия

Репутация: нет
Всего: 12



У меня получается нестандартная ситуация. Дочка-это уже готовая (не моя) прога. Кроме как использовать Hook не вижу выхода... Может есть лучшие варианты?

Это сообщение отредактировал(а) kapbepucm - 29.8.2007, 08:48


--------------------
(С) kapbepucm
PM MAIL Skype   Вверх
jonie
Дата 29.8.2007, 21:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 7
Всего: 118



чТО значит "готовая не моя" ? Нет доступа к исходникам или вам лень разбираться в чужом коде? Выражайтесь яснее....

если есть исходники то:
[Ваш модуль, имеет окно hwndMainProg]
[Дочка : запускается, ей передается HWND окна главной программы (hwndMainProg)  (да хоть через параметры вызова))]
{
оработка сообщений оконных дочкой,
если нажата клавиша, то PostMessage(hwndMainProg, WM_***,wParam,lParam);
где WM_ - нужное сообщение (вплоть до своих вида WM_USER+N, N>0; или зарегистрированных через RegisterWindowMessage(), или через нечто вроде WM_COPYDATA (ну что-то подобное было для переноса данных...))
}

в главном модуле реализуете обработку того что надо (идентификацию от какой дочки сообщение тоже можете сделать как-то дополнительно....)
Можете для связи использовать пайпы или сетевое соединение... вариантов межпроцессорного взаимодействия не один (ябы наверно юзал пайпы (pipes)..)...

Если исходников нет - тогда хук в главном модуле. И смотреть какой окно активно (например) по нему идентифицировать дочку во время обработки в хук-процедуре клавиатурного сообщения....

В общем хотите чтобы подсказали более конкретно описывайте проблему.. мыж не гадалки)


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
kapbepucm
Дата 30.8.2007, 10:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 993
Регистрация: 14.6.2007
Где: Латвия

Репутация: нет
Всего: 12



Цитата(jonie @  29.8.2007,  21:32 Найти цитируемый пост)
мыж не гадалки
Дочка- *.exe без исходников. Моя ситуация не позволяет создавать DLL (другой язык программирования, не важно какой). В общем, меня заинтересовал параметр dwThreadId. Думал, можно конкретно указать на что Hook вешать (типа, зачем вешать на всё, если есть возможность указать куда).

Это сообщение отредактировал(а) kapbepucm - 30.8.2007, 10:33


--------------------
(С) kapbepucm
PM MAIL Skype   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.1083 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.