SetWindowsHookEx не вызывает мой обратный вызов?

Ну, я пробовал другое решение моей проблемы, но оно просто не работает.

Я вызываю SetWindowsHookExA, а затем, когда я нажимаю клавишу, окно сообщения не отображается. Что делать?

это мой код (это DLL, которая загружается другой DLL, загружаемой программой):

#include <Windows.h>

HINSTANCE gl_hThisInstance = NULL;
HHOOK hHook = NULL;

LRESULT CALLBACK KeyHit(int code,WPARAM wParam,LPARAM lParam);

BOOL APIENTRY DllMain( HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
        case DLL_PROCESS_ATTACH:
         gl_hThisInstance = (HINSTANCE)hModule;
         hHook = SetWindowsHookExA(
            WH_KEYBOARD,
            KeyHit,
            //(HWND)gl_hThisInstance//not working
            0,//not working
            //(DWORD)gl_hThisInstance//not working
            //GetCurrentThreadId()//even not working with this
            0//not working
            );
        break;
    }
    return TRUE;
}

LRESULT CALLBACK KeyHit(int code,WPARAM wParam,LPARAM lParam)
{
    MessageBox(0,"PRESSED","PRESSED",0);
    return CallNextHookEx(hHook,code,wParam,lParam);
}

person Community    schedule 13.12.2012    source источник
comment
Почему актерский состав HOOKPROC? Если компилятор не выполняет это преобразование молча, то подпись KeyHit неверна.   -  person Puppy    schedule 13.12.2012
comment
Я удалил (HOOKPROC), и он отлично компилируется, поэтому я думаю, что проблема не в этом.   -  person    schedule 13.12.2012
comment
Зачем ты кастуешь gl_hThisInstance› Это уже правильный тип...   -  person Mooing Duck    schedule 13.12.2012
comment
Когда вы говорите (DWORD)gl_hThisInstance//not working, что это значит?   -  person Mooing Duck    schedule 13.12.2012
comment
Кроме того, первым параметром DllMain является HINSTANCE так что это тоже не повод кастовать.   -  person Mooing Duck    schedule 13.12.2012
comment
// не работает, значит, я пробовал это (скомпилировал плагин), но он не обнаруживает нажатия клавиш.   -  person    schedule 13.12.2012
comment
Это работает для меня SetWindowsHookEx(WH_GETMESSAGE, MsgProc, hiLib, GetWindowThreadProcessId(hwnd, NULL));   -  person Stan    schedule 13.12.2012
comment
@Stan, в вашем приложении или DLL? а я про WM_KEYBOARD   -  person    schedule 14.12.2012
comment
@GamErix Ну, я полагал, что хук сообщения из моего реального приложения может работать и для вас с клавиатурным хуком. Да, это DLL, внедренная во внешние процессы.   -  person Stan    schedule 14.12.2012


Ответы (1)


Раньше у меня были проблемы с подключением. На самом деле это не проблема, но то, как я это сделал, не должно было. Прежде всего, у вас должно быть 2 экспортированные функции из DLL, SetHook и RemoveHook. Функция SetHook будет вызывать SetWindowsHookEx() оттуда. Если вы когда-нибудь попытаетесь вызвать SetWindowsHookEx() из потока или DLLMain вашей DLL, функция не вернет ошибок, но функция обратного вызова никогда не будет вызвана. Мне понадобилось иногда, чтобы понять это.

Здесь размещен мой рабочий код для отлова WH_GETMESSAGE, на который можно ссылаться здесь.

Вот моя рабочая экспортированная функция SetHook() из DLL.

bool __declspec(dllexport) __stdcall SetHook(DWORD myWnd)
{
    mySavedHook = SetWindowsHookEx(WH_GETMESSAGE,
        GetMsgProc,
        infoContainer.DllHModule,
        myWnd);

    int errorID = GetLastError();
    if (errorID != 0)
    {
        MessageBoxA(NULL, "Failed to implement hook", "Failed", 0);
        MessageBoxA(NULL, to_string(errorID).c_str(), "Error ID", 0);
        return false;
    }
    else
    {
        return true;
    }
}

infoContainer.DllHModule: экземпляр DLL, который является первым параметром DllMain(). myWnd: — это мой идентификатор потока (не идентификатор процесса). Получите его от GetWindowThreadProcessId(window_handle, NULL). Чтобы реализовать глобальный хук, используйте 0 как myWnd.

И вот моя функция обратного вызова.

LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    if (nCode >= 0)
    {
        LPMSG msg = (LPMSG)lParam;
        if (msg->message == WM_CALLFUNCTION)
        {
            MessageBoxA(NULL, "Receive WM_CALLFUNTION", "Good news", 0);
        }

    }
    //Doesn't matter, just call this function and return it.
    return CallNextHookEx(_hook, nCode, wParam, lParam);
}

Функция обратного вызова должна иметь ключевое слово CALLBACK для работы.

Из внешнего приложения вызовите SetHook() из DLL и используйте идентификатор потока в качестве параметра.

person Hao Nguyen    schedule 15.01.2015
comment
Я не знаю, почему кто-то отредактировал ответ, просто добавив пробелы до и после кода? - person Hao Nguyen; 16.03.2017
comment
Привет, у меня та же проблема, что и у ОП. Вы предлагаете экспортировать функции SetHook() и RemoveHook(). У меня вопрос, откуда их вызывать. Мы не можем вызывать их из DllMain() или потока в DLL, потому что хуки не будут вызываться, как вы сказали (и я тоже могу это подтвердить). Мы также не можем вызывать их из приложения, в которое внедряется DLL, потому что мы не можем изменять его код. Другое приложение? Тогда он должен будет вызвать LoadLibrary()\GetProcAddress()? Или как еще? Не могли бы вы пролить немного света здесь? - person Constantine Georgiou; 27.08.2019
comment
@ConstantineGeorgiou Вы узнали, откуда вызывать эти функции? - person Itay; 13.05.2020
comment
@ Itay, лучший способ, который я нашел (хотя, вероятно, не лучший в целом или рекомендуемый), - это создать .exe-файл запуска, который будет вызывать экспортированную функцию в .dll, которая будет устанавливать ловушки. И хуки должны быть размещены в общем сегменте данных, используя директивы компилятора/компоновщика в коде, потому что пусковая установка и внедряемое приложение — это два отдельных процесса, и, таким образом, в противном случае экземпляры создавались бы дважды. - person Constantine Georgiou; 16.05.2020