Newsgroup: it.comp.lang.visual-basic
Titolo: SetWindowsHookEx

Sono riuscito a buttare giù 4 righe di codice VB per questo tipo di 
hook, per intercettare i tasti a basso livello.
Ci sono riuscito, ok, ma una volta lanciato il programma il resto 
comincia a dare un po' i numeri.
Ad esempio se faccio click sul menu di avvio, il menu si apre e si 
richiude...
Dove sbaglio???
Ecco il codice:
----------------
Form principale:
----------------
Private Sub Form_Load()
     KBDHandle = SetWindowsHookEx(WH_KEYBOARD_LL, AddressOf MiaProc, 
App.hInstance, 0&)
End Sub
Private Sub Form_Unload(Cancel As Integer)
     If KBDHandle <> 0 Then UnhookWindowsHookEx KBDHandle
End Sub
----------------
Modulo standard:
----------------
Private Const WH_KEYBOARD_LL = 13&
Public Declare Function SetWindowsHookEx Lib "user32" Alias 
"SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, ByVal 
hmod As Long, ByVal dwThreadId As Long) As Long
Private Declare Function CallNextHookEx Lib "user32" (ByVal hHook As 
Long, ByVal ncode As Long, ByVal wParam As Long, lParam As Any) As Long
Public Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As 
Long) As Long
Private Type KBDLLHOOKSTRUCT
   vkCode As Long
   scanCode As Long
   flags As Long
   time As Long
   dwExtraInfo As Long
End Type
Public KBDHandle As Long
Dim DATAINFO As KBDLLHOOKSTRUCT
Public Function MiaProc(ByVal Code As Long, ByVal wParam As Long, ByVal 
lParam As Long) As Long
     MiaProc = CallNextHookEx(KBDHandle, Code, wParam, ByVal lParam)
End Function
Ecco... dov'è che sbaglio?
-- 
Rivolterò il mondo per trovarlo, e anche se andasse in Indocina uno dei 
nostri starà nascosto in una ciotola di riso pronto a sparargli nel culo.
(Pulp Fiction)

 End Function
Aggiungo che quel "byVal lParam" nella chiamata a CallNextHookEx l'ho 
aggiunto nei vari tentativi. In origine passavo semplicemente lParam 
senza il byVal ma niente da fare...


 App.hInstance, 0&)
[cut]
Public Declare Function SetWindowsHookEx Lib "user32" Alias
"SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, ByVal
hmod As Long, ByVal dwThreadId As Long) As Long
[cut]
Vado a spanne, visto che il codice che avevo scritto io tempo addietro non
ce l'ho piu' sottomano...
Cmq, dall'MSDN ho tirato fuori questo (guarda la definizione della funzione
che hai postato tu e che ho riportato piu' sopra):
L'indirizzo della procedura di Hook (parametro lpfn) deve essere O
all'interno di una DLL O all'interno del processo corrente.
Se la piazzi in una DLL, il parametro hmod deve essere l'handle alla DLL in
cui si trova l'Hook ed il parametro dwThreadId essere 0.
Se invece la piazzi nel processo corrente, il parametro hmod deve essere
NULL ed il parametro dwThreadId deve essere quello di un Thread del
processo.
Ora, cosi' ad occhio mi sembra che tu l'abbia messa in un eseguibile (anche
perche' le DLL in VB non puoi farle, quindi...)
E la chiamata  SetWindowsHookEx(WH_KEYBOARD_LL, AddressOf MiaProc,
App.hInstance, 0&)
gli passa l'indirizzo di un Hook associato al processo corrente, pero' poi
gli passi l'hInstance del processo (che non e' un Handle ad una DLL), e 0
come threadid.
Prova, al limite, a chiamarla cosi':
SetWindowsHookEx(WH_KEYBOARD_LL, AddressOf MiaProc, 0&, App.ThreadID)
(non garantisco la correttezza di quanto digitato, visto che non ho un VB
installato per vedere dove va' la h in threadID, ne se la proprieta' si
chiama proprio cosi' :-D )
Scusa la prolissaggine :-)

 SetWindowsHookEx(WH_KEYBOARD_LL, AddressOf MiaProc, 0&, App.ThreadID)
Ci ho provato, ma non hooka.
Ho fatto:
VecchioHANDLE = SetWindowsHookEx(WH_KEYBOARD_LL, AddressOf MiaProc, 0&, 
App.ThreadID)
e mi ritorna VecchioHANDLE = 0 (quindi non è riuscito ad agganciare nulla).
Ho provato a passare NULL come valore ma mi dice "Utilizzo non valido di 
Null".
Facendo invece
VecchioHANDLE = SetWindowsHookEx(WH_KEYBOARD_LL, AddressOf MiaProc, 
App.ThreadID, 0&)
e mi restituisce VecchioHandle<>0 che vuol dire che ha hookato!!!
Infatti poi nella MiaProc richiamo SEMPRE CallNextHookEx senza 
modificare i dati e tutto funziona nel senso che non perdo informazioni. 
Però tutto il resto si comporta stranamente......
intanto cerco degli esempi su Goooooogle (e grazie per l'aiuto)


Ho trovato l'errore: la costante WH_KEYBOARD_LL era dichiarata come 
privata nel modulo, quindi dal form inviavo uno 0 al posto del suo 
valore hookando non so cosa (forse qualsiasi messaggio...).
Ora che però ho agganciato la keyboard_low_level non riesco a modificare 
i tasti.
Se nella MiaProc NON RICHIAMO nessun CallNextHookEx, i processi restanti 
(compreso il mio programma) ricevono lo stesso i dati!!!
Che fo?


HO RISOOOOOOLTOOOOOOOOOOOOOOOOOOOOO!!!! ;) ;) ;) ;) ;) ;)
Scusate l'urlo ma era uno sfogo!!!!!!!
Allora: m'ero scordato che dal valore tornato dalla mia proc dipendevano 
gli altri processi: quindi se voglio bloccare dei tasti (almeno per ora 
so fare questo), devo far restituire un valore non-zero alla mia proc:
Public Function MiaProc(ByVal Code As Long, ByVal wParam As Long, ByVal 
lParam As Long) As Long
Dim DATAINFO As KBDLLHOOKSTRUCT
     If Code = 0 Then
         Call CopyMemory(DATAINFO, ByVal lParam, Len(DATAINFO))
         If DATAINFO.vkCode = 65 Then
             MiaProc = 1
         Else
             MiaProc = CallNextHookEx(KBDHandle, Code, wParam, lParam)
         End If
     Else
         MiaProc = CallNextHookEx(KBDHandle, Code, wParam, lParam)
     End If
End Function
e così blocco la pressione del tasto 'A'.
Ho provato e neanche con il notepad riesco a digitare la lettera A.
Ora devo vedere come riassegnare i tasti :)
Nulla di preoccupante, non mi diverto a fare i programmini che 
infastidiscono gli utenti eh?
Però se riesco a fare bene questo probabilmente potrò divertirmi a 
hookare le chiamate ai metodi grafici etc. etc.


 Ci ho provato, ma non hooka.
[cut]
Azz...sto' invecchiando cosi' male?
Scusa, non per portarti sfiga, ma provi a compilarlo e lanciare il
compilato? (della versione che ti funziona, chiaramente)

 compilato? (della versione che ti funziona, chiaramente)
Si ci avevo già provato, non funziona.
Bisogna passare prima App.hInstance e poi 0&.
Comunque l'errore alla fine era nella dichiarazione della costante 
KH_KEYBOARD_LL che nel modulo era privata e quindi dal form, non 
vedendola, passavo probabilmente uno 0 alla SetWindowsHookEx.
Ora il problema è: quando intercetto dei tasti, posso cambiare il loro 
valore prima di passare i dati alle altre hook?
Ci ho provato col copy memory verificando anche quello che succedeva, ed 
effettivamente RIPRENDENDO i dati dalla zona puntata da lParam mi 
ritrovavo con i dati che dicevo io, solo che alla fine per il S.O. non 
cambiava nulla e la mia app e le altre continuavano a ricevere i giusti 
dati.
Come posso cambiare i dati ricevuti prima di passarli alle altre 
applicazion con CallNextHookEx?


 Bisogna passare prima App.hInstance e poi 0&.
Uhmmm...la cosa continua a non quadrarmi. Teoricamente, il compilato non
dovrebbe funzionare...cioe', la tua versione che funziona, quella
SetWindowsHookEx(WH_KEYBOARD_LL, AddressOf MiaProc, App.ThreadID, 0&)
Al massimo dovrebbe funzionare SOLO dall'IDE, e mi torna strano pure li'.
Se ne hai voglia e non ti crea problemi, mi manderesti il progetto che
volevo fare una prova?

 volevo fare una prova?
Appena torno a casa prima di mettermi a riesumare il vecchio HD (vedi 
qualche thread più sopra) ti rarro/zippo il progetto e te lo spedisco.
La mail indicata qui nel NG è corretta? Devo togliere/aggiungere 
qualcosa all'indirizzo che si vede?


 qualcosa all'indirizzo che si vede?
Correttissima, non ho antispam nell'indirizzo email.

 vedendola, passavo probabilmente uno 0 alla SetWindowsHookEx.
Vuoi dire che tu lavori di hook e subclassing senza l'option explicit?
Ciao
--
Math Parser : 
http://www.neodatatype.net
FlowChart   : 
http://www.neodatatype.net/dump/flowchart/dir.asp
Sito Comune : 
http://www.it-lang-vb.net

> Vuoi dire che tu lavori di hook e subclassing senza l'option explicit?
Ahem....
Capita che dimentichi di usarlo(usarla?) perchè sto cercando ancora di 
*prendere l'abitudine*...


 qualcosa all'indirizzo che si vede?
;__;
Funziona!!! :_(
Signori vi saluto, vado in pensione e passo a fare il camionista!!!

 *prendere l'abitudine*...
Impostalo come default e prendi in fretta l'abitudine di controllare la 
sua presenza in ogni modulo.
