Newsgroup: it.comp.programmare.win32
Titolo: Aiutatemi please """""""!!!!!!!!!!!!!!!!!!

Stò cercando di realizzare un applicazione che sia in grado di catturare
tutti i tasti premuti
della tastiera qualsiasi sia l'applicazione che abbia il fuoco di tastiera.
Pertanto ho realizzato una applicazione che chiama una dll nella quale
utilizzo
la funzione SetWindowHookEx(), fin quà tutto bene, tuttavia nn riesco a
capire perchè nn
catturo tutti i tasti di tutti i thread visto che come ultimo parametro
passo il valore 0 (cioè tutti i thread come dichiara msdn), ma solo i chars
della mia applicazione fintanto che ha il fuoco di tastiera.
Qui di seguito vi riporto le parti salienti del codice :
//CODICE DLL
#pragma data_seg ("shared")
static HHOOK hKeyboardHook=0;
HWND hDlg=NULL;
#pragma data_seg ()
#pragma comment(linker,"/SECTION:shared,RWS")
EXPORT LRESULT CALLBACK KeyboardHookProc(int nCode, WPARAM wParam, LPARAM
lParam)
{
	const KEY_UP=0x80000000;
	const KEY_WAS_DOWN=0x40000000;
	if(nCode<0)
		return CallNextHookEx(hKeyboardHook,nCode,wParam,lParam);
	if(nCode==HC_ACTION)
	{
		if(!(lParam & KEY_WAS_DOWN))
		{
                                     ....
		}
	}
	return CallNextHookEx(hKeyboardHook,nCode,wParam,lParam);
}
BOOL APIENTRY DllMain( HINSTANCE hModule,DWORD ul_reason_for_call,LPVOID
lpReserved)
{
 
	 switch (ul_reason_for_call)
	{
		case DLL_PROCESS_ATTACH:
		break;
		case DLL_THREAD_ATTACH:
hKeyboardHook=SetWindowsHookEx(WH_KEYBOARD,KeyboardHookProc,hModule,0);
		break;
		case DLL_THREAD_DETACH:
			UnhookWindowsHookEx(hKeyboardHook);
		break;
		case DLL_PROCESS_DETACH:
		break;
    }
    return TRUE;
}
//codice applicazione
HINSTANCE hGlobalInst=NULL;
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM
lParam)
{
     PAINTSTRUCT ps ;
     static UINT iDataChangeMsg ;
     switch (message)
     {
	 case WM_CREATE:
  iDataChangeMsg = RegisterWindowMessage (TEXT ("StrProgDataChange")) ;
   hGlobalInst=LoadLibrary(TEXT("strlib.dll"));
	  return 0 ;
 
 
                case WM_KEYDOWN:
	  KeyboardHookProc(HC_ACTION, wParam, lParam);
	  break;
 
 
	 case WM_PAINT: BeginPaint (hwnd, &ps) ; EndPaint (hwnd, &ps) ; return 0 ;
 
	 case WM_DESTROY: PostQuitMessage (0) ; return 0 ;
	 default:
	  if (message == iDataChangeMsg)
			  {
	KeyboardHookProc(HC_ACTION, wParam, lParam);
			  }
			  break ;
		 }
 return DefWindowProc (hwnd, message, wParam, lParam) ;
}
Qualsiasi suggerimento sarà ben gradito. Se avete del codice di esempio
sulla gestione delle dll mandatemelo pure.
grazie
Alex
--------------------------------
Inviato via 
http://usenet.libero.it

 la funzione SetWindowHookEx(), fin quà tutto bene, tuttavia nn riesco a
Ti ho risposto più giù.
Innanzitutto la setecc. falla dentro al tuo processo 1 volta soltanto. Se la
fai sull'attach ti viene richiamato 1 volta per ogni processo che se la
innietta nel virtual address e questo può creare casini.
Per il resto dimmi se così risolvi poi al limite vedo.
P.s. la callback ovviametne rimane dentro alla dll perchè appunto deve
essere iniettabile in tutti i processi.

 essere iniettabile in tutti i processi.
Se setto l'hook nella create della mia finestra, però che hInstance gli
passo come terzo
parametro?? l'hInstance del mio processo???
poi mi dici che la Proc per catturare tutti i tasti deve essere
esportabile...il compilatore
mi dice che non riconosce l'identificatore della Proc anche se nel .h della
dll
ho messo
EXPORTS LRESULT CALLBACK KeyboardHookProc(int nCode, WPARAM wParam, LPARAM
lParam);
e nel .h della mia applicazione ho messo #include "headerdll.h"
di seguito il codice se vuoi dargli un occhio :
//=========================================================
//.h dell'applicazione finestra. Non c'è nulla di strano,credo, è codice
generato in //
// automatico da Visual Studio
#if !defined(AFX_KBH_H__1236CF36_DF83_11D6_B842_444553540000__INCLUDED_)
#define AFX_KBH_H__1236CF36_DF83_11D6_B842_444553540000__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "resource.h"
#endif //
!defined(AFX_KBH_H__1236CF36_DF83_11D6_B842_444553540000__INCLUDED_)
//=========================================================
//.cpp dell'applicazione finestra
HINSTANCE hInst; // current instance
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // The title bar text
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	int wmId, wmEvent;
	PAINTSTRUCT ps;
	HDC hdc;
	TCHAR szHello[MAX_LOADSTRING];
	LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);
	switch (msg)
	{
 
		case WM_CREATE:
			hGlobalInst=LoadLibrary(TEXT("hkey.dll"));
//Qui il compilatore mi dice che KeyboardHookProc non è dichiarata ma se
guardi sotto nel .h //della dll
SetWindowsHookEx(WH_KEYBOARD,KeyboardHookProc,hInst,0);
 
			if(!hGlobalInst)
				PostQuitMessage(0);
		break;
//=========================================================
//.h della dll
#define EXPORTS __declspec(dllexport)
EXPORTS LRESULT CALLBACK KeyboardHookProc(int nCode, WPARAM wParam, LPARAM
lParam);
//=========================================================
//.cpp della dll
//#pragma data_seg ("shared")
	static HHOOK hKeyboardHook=0;
	HWND hDlg=NULL;
/*
#pragma data_seg ()
#pragma comment(linker,"/SECTION:shared,RWS")
*/
EXPORTS LRESULT CALLBACK KeyboardHookProc(int nCode, WPARAM wParam, LPARAM
lParam)
{
	const KEY_UP=0x80000000;
	const KEY_WAS_DOWN=0x40000000;
	if(nCode<0)
		return CallNextHookEx(hKeyboardHook,nCode,wParam,lParam);
	if(nCode==HC_ACTION)
	{
		if(!(lParam & KEY_WAS_DOWN))
		{
			...qui catturo tutti i tasti premuti
		}
	}
	return CallNextHookEx(hKeyboardHook,nCode,wParam,lParam);
}
BOOL APIENTRY DllMain( HINSTANCE hModule,DWORD ul_reason_for_call,LPVOID
lpReserved)
{
 
	 switch (ul_reason_for_call)
	{
		case DLL_PROCESS_ATTACH:
		break;
		case DLL_THREAD_ATTACH:
		break;
		case DLL_THREAD_DETACH:
		break;
		case DLL_PROCESS_DETACH:
		break;
    }
    return TRUE;
}
qualche suggerimento???
grazie in anticipo per qualsiasi dritta.


 ho messo
Devi caricare la dll a runtime con LoadLibrary.
Per ricavare l'indirizzo della hookproc devi usare GetProcAddress.
esempio
    HINSTANCE hHandle;
    HOOKPROC ProcAddress;
    hHandle= LoadLibrary("xxx.dll");
    if (hinstLib != NULL)
    {
        ProcAddress= (HOOKPROC ) GetProcAddress(hHandle,
"nomeproceduralastessadiexport");
   }


 
Ok,ho usato la getProcAdress,e catturo i tasti fintanto che ho il fuoco di
tastiera sulla
mia applicazione, ma se poi cerco di catturare i tasti di un altra
applicazione con il fuoco
mi viene segnalato errore di IExplorer o kernel al n°di pagina.Perché?
Forse dovrei rilasciare l'hook quando perdo il fuoco, e difatti ho provato
ad usare nel WM_KILLFOCUS la UnhookWindowsHookEx() passandogli come
parametro l'hook
che ottengo dalla setwindowhook, ma il problema non si risolve (e seguendo
questa logica dovrei risettare l'hook quando riottengo il fuoco).
Qualche suggerimento?


 questa logica dovrei risettare l'hook quando riottengo il fuoco).
Rimuovendo e reinstallando l'hook non ti cambia nulla perchè cmq  i tasti
che l'hook cattura passano sempre dall wndproc della finestra col focus.
Fai andare la DLL in debug e attiva la gestione delle eccezzioni "Always
Stop" . Come eseguibile per debub mettici il tuo prog che installa l'hook.
Guarda se il crash è dentro alla dll iniettata in quel processo.
Se il crash (come purtroppo suppongo) è interno ad un altro processo le cose
si fanno più incasinate.
In questo caso per non complicarti la vita puoi piazzare dei
OutputDebugString in punti strategici della dll per vedere il punto esatto
dove crasha. Per vedere gli outpudebugstring ti passa fare l'attach del
debug ad un qualunque processo attivo.

 si fanno più incasinate.
Con Visual C 6.0 si possono gestire le eccezioni?!? Dov'è?^?^^?^?^


> Con Visual C 6.0 si possono gestire le eccezioni?!? Dov'è?^?^^?^?^
E come no? :-) basta far partire il debug (attach to process o run da
codice) e quindi entrare nel menu debug - Exception...
Per quanto riguarda il tuo problema penso di aver capito l'inghippo.
Innanzitutto non ho ben chiaro perchè sull'attach to thread chiami la
keyboardproc. Essendo una callback non dovrebbe mai essere chiamata così in
modo diretto...
Cmq secondo me il ciocco te lo fa il callnexthookex: il parametro hHook come
glielo passi?
l'hHook viene restituito dalla setwindowhookex che però tu chiami dalla tua
app. La validità di questo handle viene persa per le copie della dll
(dovresti duplicare l'handle manualmente ma il metodo più diretto e farlo
fare alla dll stessa).
La soluzione è:
Crea 2 funzioni : installHook e uninstallHook dentro alla dll.
Una setta l'hook, l'altra lo leva.
L'handle hHook a questo punto sarà interno alla dll e dalla tua app non
dovrai più chiamare direttamente la setwindowhookex ma chiamerai le funzioni
install ecc.
Spero di non averti fatto troppa confusione cmq in definitiva viene così:
BOOL WINAPI DllMain( HINSTANCE hinstDLL,  DWORD fdwReason,  LPVOID
lpvReserved)
{
 g_hHook = NULL;
 g_hInstance = hinstDLL;
 return TRUE;
}
LRESULT CALLBACK HookProc( int nCode,  WPARAM wParam,  LPARAM lParam)
{
***  Tuo codice qui ******
return  CallNextHookEx (g_hHook,nCode,wParam,lParam);
}
void InstallHook(void)
{
  if (!g_hHook)
 {
   g_hHook = SetWindowsHookEx( ... , HookProc, g_hInstance, NULL);
  }
 }
void UninstallHook (void)
{
 UnhookWindowsHookEx,hHook(g_hHook);
  g_hHook = NULL;
}

 install ecc.
Le funzioni Install & UnInstall probabilmente non le chiamo nel posto
giusto?!?!?!?!


 giusto?!?!?!?!
A mio avviso andava bene nel primo metodo (con l'install nel create e
l'uninstall nel destroy). Dimmi il problema che ti da nel dettaglio.
In ogni caso non puoi settare un hook sulla thread attach della dll perchè
la dll viene iniettata su tutti i processi che spediscono eventi di tastiera
(e quindi perlomeno altrettanti thread): ti troveresti tanti hook dello
stesso tipo in catena quanti sono i processi con user interface...

 Perchè static? non basta che sia globale?
Ok scusa mi sono fatto una dormita...

 In ogni caso che problema ti da?
Ma allora che senso ha utilizzare una dll?
Non ho mai utilizzato il link statico?
Come faccio nella wm_create a chiamare la funzione EXPORTS InstallHook(...)
dichiarata nella dll????


 dichiarata nella dll????
Nei parametri "input" del link devi usare la .lib che ti ha generato il
compilatore della dll.
In più devi includere il .h con il prototipo della definizione della
funzione.
E' la stessa cosa che fai quando usi una qualunque API solo che in vc++ è
implicito (mentre in VB devi farlo esplicitamente).
Considera ad esempio la funzione CreateFile tu la usi liberamente ma in
realtà puoi farlo perchè sotto sotto viene incluso il winbase.h (tramite la
windows.h) e viene linkata la kernel32.lib...
Cmq mi dici una cosa? che sistema operativo usi? Io su winxp ho creato uno
scuff con un hook globale e funziona perfettamente al massimo lo sistemo e
te lo passo così ci dai un occhiata.

 te lo passo così ci dai un occhiata.
Uso Win98SE. Allora provo a caricare la lib anzichè la dll, che dovrebbe
essere l'unica cosa
che mi manca, cmq passami il tuo code, è pur sempre un ottimo modo per fare
esercizio, senza contare che forse ci sono delle differenze tra Win9x e
WinXp.
Ti farò sapere.
Bye.


 te lo passo così ci dai un occhiata.
Mi si inchioppa il sistema (win98se), dopo aver tolto il fuoco dalla mia
app, sia se digito
dalla riga di commando sia se avvio ad esempio worpad e inizio a scrivere.
