Здравствуйте, 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);
зы.. все это, неоднократно обсуждалось на форуме