Re[10]: Я в шоке GetMessage()
От: Ovl Россия  
Дата: 13.09.05 08:48
Оценка: 3 (1) +1
Здравствуйте, Votblin, Вы писали:

V>Спасибо за ответ. Но чтот я и та ки сяк пытался поюзать этот хук. Ничего не выходит.


V>МОжет подскажете все таки?


посмотрел я посты — действительно, хук + сабклассинг более верно.
делается это примерно так.

нам потребуется dll c двумя процедурами. одна из них будет хук-процедурой, вторая — новой оконной процедурой.
то есть интерфейс такой


// hookDll.h

// экспортируется из длл
void DLL_EXPORT SetHook( HMODULE currentModule );
void DLL_EXPORT ClearHook( HMODULE currentModule );
LRESULT CALLBACK DLL_EXPORT CBTProc(int nCode, WPARAM wParam, LPARAM lParam);


про тело можно позже поговорить.
можно поставить так ( это уже исходник приложения, то есть exe-шника)

// appUsingHook.cpp

typedef void ( *STARTHOOKPROC )();

void ApplicationSetHook() {
    HMODULE dll = LoadLibrary("hookDll.dll");
    if ( dll != INVALID_HANDLE_VALUE ) {
        STARTHOOKPROC proc = (STARTHOOKPROC) GetProcAddress( dll, "SetHook" );
        if ( proc != NULL ) {
            proc( dll );
        }
        FreeLibrary( dll );
    }
}    

void ApplicationClearHook() {
    HMODULE dll = LoadLibrary("hookDll.dll");
    if ( dll != INVALID_HANDLE_VALUE ) {
        STARTHOOKPROC proc = (STARTHOOKPROC) GetProcAddress( dll, "ClearHook" );
        if ( proc != NULL ) {
            proc( dll );
        }
        FreeLibrary( dll );
    }
}


здесь удобно, что все функции, выставляющие хук находятся внутри самой dll, и таким образом получают премущество в виде shared memory section. образно говоря, внутри dll можно сделать память, которая будет общей для этой dll, даже если она была загружена в другой процесс.

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


//hookDll.cpp
HHOOK hook;

WNDPROC oldProc = NULL;
void SubclassWindow( HWND hwnd );
LRESULT CALLBACK NewWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);


void DLL_EXPORT SetHook( HMODULE currentModule ) {
    hook = SetWindowsHookEx( WH_CBT, CBTProc, currentModule, 0 );
}

void DLL_EXPORT ClearHook() {
    UnhookWindowsHookEx( hook );
}

LRESULT CALLBACK DLL_EXPORT CBTProc(int nCode, WPARAM wParam, LPARAM lParam) {
    if ( nCode < 0 )
        return CallNextHookEx( hook, nCode, wParam, lParam );
    
    switch ( nCode ) {
        case HCBT_CREATEWND: {
            if ( lp->lpszClass != 0 && stricmp(lp->lpszClass, "WindowClassName") == 0 ) {
                SubсlassWindow( (HWND) wParam );
            }
            break; }
    }
    return CallNextHookEx( hook, nCode, wParam, lParam ); }
}

void SubclassWindow( HWND hwnd ) {
    if ( oldProc == NULL ) {
        oldProc = SetClassLongPtr( hwnd, GCLP_WNDPROC, NewWndProc );
    }
}

LRESULT CALLBACK NewWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch ( msg ) {
        case WM_KEYDOWN {
            ::MessageBox( hwnd, "You pressed key", "KEY", MB_OK );
        }
    }
    return oldProc( hwnd, msg, wParam, lParam );
}


момент — CallNextHookEx() получает хендл хука, который был установлен. а если я устанавливаю его в одном процессе, например, в своем, а он потом вызывается другой, например из калькулятора:
1) в адресное пространство калькулятора загружается hookDll.dll
2) там ищется функция CBTProc
3) вызывается оная.

и внутри неё нам нужно вызвать следующий хук ( они там в очереди все стоят ). но SetWindowsHookEx я вызывал в другом процессе, значит и хендл хука в другом процессе. вот тут-то и пригодятся shared memory section. они позволяют сказать линкеру, что вот эта область память будет доступна для всех длл, неважно где и когда они загрузились.
конкретно, в эту область нам надо поместить HHOOK hook. в результате получается


//hookDll.cpp
#pragma data_seg( .shared ) 
HHOOK hook = NULL;
#pragma data_seg() 
#pragma comment(linker, /section:.shared,RWS )

WNDPROC oldProc = NULL;
void SubclassWindow( HWND hwnd );
LRESULT CALLBACK NewWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);



зы.. все это, неоднократно обсуждалось на форуме
Read or Die!
Как правильно задавать вопросы
Как правильно оформить свой вопрос
Автор: anvaka
Дата: 15.05.06
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.