хук на клавитару - проблема
От: AlexJH  
Дата: 16.07.09 20:17
Оценка:
Задача: поставить глобальный хук на клавиатуру, при нажатии любой клавиши создавать файл с заданным именем.
приложение:
#include <string>
#include <iostream>
#include <conio.h>
#include <windows.h>

static HHOOK*    HookHandle  = NULL;            
HOOKPROC HookProc = NULL;

int main()
{
    HINSTANCE DllHandle = LoadLibrary(L"SharedDll.dll");      
    if( DllHandle )                           
    {                                                        
        //хук - процедура
        HookProc = (HOOKPROC) GetProcAddress( DllHandle, "_HookProc@12");   
        //хэндл библиотеки
        HookHandle = (HHOOK*) GetProcAddress( DllHandle, "dllHook" ); 
        //установка хука
        *HookHandle = SetWindowsHookExW( WH_KEYBOARD, HookProc, DllHandle, NULL );     
        _getch();
        MessageBox(NULL,L"text",L"title",NULL);
        UnhookWindowsHookEx(*HookHandle);       
        FreeLibrary(DllHandle);       
    }
    else
    {
        MessageBox(NULL,L"Failed to load library",L"error",0);
    }
    return 0;
}


DLL:
//секция разделяемой памяти
#include <windows.h>
#include <iostream>

#pragma data_seg(".myseg")
extern "C" __declspec(dllexport)    HHOOK dllHook = NULL;  
#pragma data_seg()
#pragma comment(linker, "/SECTION:.myseg,RWS") 

extern "C" __declspec(dllexport)                              
LRESULT CALLBACK HookProc(                  
                          int code,                               
                          WPARAM wParam,                          
                          LPARAM lParam 
                          )
{      
    fclose(fopen("c:\\PROVERKA.jpg","w"));
    return CallNextHookEx(dllHook, code, wParam, lParam );  
}


Я запускаю приложение, делаю его неактивным (т.к. хук не перехватывает нажатие клавиш на консоль), щёлкаю любую клавишу, и получаю PROVERKA.jpg на диске c:\.
Проблема: стоит мне заменить "c:\\PROVERKA.jpg" на "PROVERKA.jpg" или любое другое имя без абсолютного пути ("xxx.xxx"), то всё совершенно меняется. Поведение: запускаю программу, убираю на задний фон, щёлкаю любую клавишу — ничего не происходит. Когда в конце приложения выскакивает
MessageBox(NULL,L"text",L"title",NULL), то только тогда, делая активным любое окно (даже консоль), я получаю PROVERKA.jpg в той же папке, что и программа.
Как вообще такое может быть? Чем абсолютный путь так кардинально отличается от относительного в моей программе?

17.07.09 10:33: Перенесено модератором из 'C/C++. Прикладные вопросы' — Кодт
Re: хук на клавитару - проблема
От: AlexJH  
Дата: 16.07.09 20:23
Оценка:
"только тогда, делая активным любое окно (даже консоль), я получаю PROVERKA.jpg в той же папке, что и программа."
Ну и нажимая какую-либо клавишу, естественно.
Re: хук на клавитару - проблема
От: -prus-  
Дата: 17.07.09 06:56
Оценка: 3 (1)
Здравствуйте, AlexJH, Вы писали:

AJH>Я запускаю приложение, делаю его неактивным (т.к. хук не перехватывает нажатие клавиш на консоль), щёлкаю любую клавишу, и получаю PROVERKA.jpg на диске c:\.

AJH>Проблема: стоит мне заменить "c:\\PROVERKA.jpg" на "PROVERKA.jpg" или любое другое имя без абсолютного пути ("xxx.xxx"), то всё совершенно меняется. Поведение: запускаю программу, убираю на задний фон, щёлкаю любую клавишу — ничего не происходит. Когда в конце приложения выскакивает
AJH>MessageBox(NULL,L"text",L"title",NULL), то только тогда, делая активным любое окно (даже консоль), я получаю PROVERKA.jpg в той же папке, что и программа.
AJH>Как вообще такое может быть? Чем абсолютный путь так кардинально отличается от относительного в моей программе?

Вы ставите глобальный хук. Ваша длл загружается в адресные пространства приложений. Если указываете полный путь "c:\file.dmp", то все будет записываться именно в этот файл от всех приложений. А когда указываете просто "file.dmp", то файл этот будет создаваться в папке каждого графического приложения, которое на момент нажатия клавиши активно.

По поводу консольного приложения и перехвата нажатий в консоле...
Нужно вызывать SetWindowsHookEx с WH_KEYBOARD_LL и также в длл создавать дополнительный поток:

LPTHREAD_START_ROUTINE WINAPI DispatchHookMsgThreadFunc(PVOID) {

    MSG msg;

    while( GetMessage(&msg, NULL, 0, 0) ) {
        DispatchMessage(&msg);
    }

    return 0;
    
}


Таким образом можно будет отлавливать клавиши во всех графических приложениях включая cmd.
Почитайте про WH_KEYBOARD_LL тут.
С уважением,
Евгений
Re[2]: хук на клавитару - проблема
От: AlexJH  
Дата: 17.07.09 11:53
Оценка:
Евгений, большое спасибо!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.