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

Salve a tutti! Spero di non essere OT.
Allora... ho creato un programma che intercetta la pressione dei tasti.
Ho usati le API SetWindowsHookEx, CallNextHookEx e UnhookWindowsHookEx.
Nella MIA procedura 'TastieraHook', che viene richiamata appena è stata
intercettata la pressione di un tasto, ho eseguito un cotnrollo: se il tasto
premuto è la A (wParam=65) allora poni wParam=32. A questo punto se dovessi
premere la A, la pressione del tasto dovrebbe produrre uno spazio.
Perchè invece le modifiche apportate a wParam non hanno effetto sulle
applicazioni?
Ad esempio se avvio il notepad quando il mio programm è attivo, posso
scrivere quello che mi pare: i tasti vengono intercettati ma le modifiche da
me effettuate non hanno effetto.
Come faccio?
Se non vi è di disturbo, vi posto il codice scritto da me.
Nel form:
-------------
Private Sub Form_Load()
    hHook = SetWindowsHookEx(WH_KEYBOARD, AddressOf Hooktastiera,
App.hInstance, 0&)
End Sub
Private Sub Form_Unload(Cancel As Integer)
    Call UnhookWindowsHookEx(hHook)
End Sub
Nel modulo:
--------------
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
Public 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
Public Const WH_KEYBOARD = 2
Public hHook As Long
Public Function Hooktastiera(ByVal nCode As Long, ByVal wParam As Long,
ByVal lParam As Long) As Long
    If wParam = 65 Then
        wParam = 32
    End If
    Form1.Print wParam
    Hooktastiera = CallNextHookEx(hHook, nCode, wParam, lParam)
End Function

Aggiungo che uso Win2000 Professional e sono loggato come administrator (non
so se potesse esservi di aiuto).

 applicazioni?
Non entro nel merito della logica, ma funzioni di quel tipo (basso livello
o, se preferisci, alta priorità) dovrebbero riconoscere il peso reale del
carattere/tasto. Ora, non so se esiste qualche parametro apposito, ma sei
sicuro che A=65 non sia molto diverso da a=97?

 sicuro che A=65 non sia molto diverso da a=97?
N.B.: Forse non avrai dato un'occhiata al mio codice, però c'è una riga che
stampa sul form il carattere appena intercettato. Se premo A (maiuscola o
minuscola), viene stampato 65 (codice virtuale). Se premo lo spazio, mi
stampa 32.
Allora dico io: se pongo wParam (che è il tasto intercettato) a 32 nel caso
sia una A, dovrebbe convertirmela in spazio, dato che poi passo la palla a
Win dandogli i nuovi parametri (modificati).

 Win dandogli i nuovi parametri (modificati).
Mi spiace, non conosco il funzinamento di quelle API, nè come passare a Win
un peso modificato...

End Sub
No, non in Windows 2000....
Private Sub Form_Load()
    hKeyProc = SetWindowsHookEx(WH_KEYBOARD_LL, AddressOf
LowLevelKeyboardProc, App.hInstance, 0&)
End Sub
Private Sub Form_Unload(Cancel As Integer)
    Call UnhookWindowsHookEx(hKeyProc)
End Sub
Public Function LowLevelKeyboardProc(ByVal nCode As Integer, ByVal
wParam As Long, ByVal lParam As Long) As Long
 
    If (nCode = HC_ACTION) Then
        If ((wParam = WM_KEYDOWN) Or (wParam = WM_SYSKEYDOWN) Or (wParam
= WM_KEYUP) Or (wParam = WM_SYSKEYUP)) Then
            Dim KbdHStruct As KBDLLHOOKSTRUCT
            CopyMemory KbdHStruct, lParam, Len(KbdHStruct)
            Debug.Print KbdHStruct.vkCode & Space(5) &
Chr(KbdHStruct.vkCode)
        End If
    End If
    'LowLevelKeyboardProc = &H1
    LowLevelKeyboardProc = CallNextHookEx(&H0, nCode, wParam, lParam)
End Function
Ciao,
Moreno
-- 
sirri at morenosoft dot com
Moreno Sirri VB Site - 
http://www.msvbsite.net
---------------------------------------------------------------------------
Le risposte alle tue domande le trovi sul Sito Comune di questo NewsGroup:
 
http://www.it-lang-vb.net
---------------------------------------------------------------------------

>             CopyMemory KbdHStruct, lParam, Len(KbdHStruct)
Ho copiato il tuo codice, ma non va: quando stampo il contenuto di
KbdHStruct.vkCode mi stampa un numeraccio abbastanza lungo. Ho guardato cosa
fa CopyMemory e come lo sto applicando: praticamente copia su tutto
KbdHStruct il contenuto di lParam. Ma se lParam è un long (4 bytes) come fa
a opiarlo su KbdHStruct che è composta da più variabili Long?
Oppure ho sbagliato a dichiarare la struttura KBDLLHSTRUCT?
Public Type KBDLLHOOKSTRUCT
    vkCode As Long
    scanCode As Long
    flags As Long
    time As Long
    extraInfo As Long
End Type

 Come faccio?
Scusa la curiosità, se cacci una txtbox sul tuo programma, e digiti dentro
alla TUA txtbox, ti fa la conversione??
Umbe

> Si. Ci ho appena provato: (ecc. ecc. ecc)
Cioè quel SI significa solo che ci ho provato, non che ci sia riuscito :(

Ho provato il programma su Win98SE e VB6.
Ovviamente non ho "hookato" usando WH_KEYBOARD_ALL perchè è indicato che
funzioni soltanto con NT4 e superiori. Ho usato semplicemente WH_KEYBOARD, e
al solito viene intercettato il tasto ma non riesco a bloccarlo nè a
modificarlo.
Nella mia procedura HookKeyboard ho addirittura tolto la riga che richiama
l'API CallNextHookEx e il programma funziona lo stesso!
Ma CallNextHookEx non serve a passare i parametri a Windows perchè il SO
continui a gestire la tastiera?

 continui a gestire la tastiera?
Mmmmm serve solo a passare il comando ad altri thread che hanno eseguito
l'hook dello stesso evento.
Insomma... come faccio a modificare un tasto ricevuto in hook?


Dunque ..attenzione....
con vb non riesci a fare degli hook globali....
Infatti se ti vuoi scrivere un bel key logger che intercetti i tasti pigiati
all'interno di qualsiasi applicazione(come note pad ad esempio), necessiti
di una dll scritta in c++ se vuoi un buon risultato.
Cerca sugli hook globali...se non erro tempo fa c'e' stato pure un articolo
su ioprogrammo di Elia Florio che spiegava come farsi un keylogger da vb e
perchè appoggiarsi ad una dll...
Umbe

KbdHStruct.vkCode mi stampa un numeraccio abbastanza lungo. 
puoi postare tutto il codice ed il risultato?
