Newsgroup: it.comp.lang.visual-basic
Titolo: Hook per la tastiera!!!

Voglio intercettare ediante gli hook della tastiera i tasti premuti e
filtralsi secondo  le mie esigenze...
Ho già del codive VB... ma non funziona in VB6...
Grazie per l'attenzione!!!1

 Ho già del codive VB... ma non funziona in VB6...
----[?] mode on
Come mai non funziona in VB6 ? Potresti farmi vedere ?
Solo per curiosità.
----[?] mode off
Ti faccio un esempio di come si può impostare un
hook di tastiera. Le dichiarazioni delle funzioni non
le scrivo.
Public Const WH_KEYBOARD = 2
Public Const VK_SHIFT = &H10
'Handle dell'hook da impostare. Public perché non
'si possono passare variabili a una callback.
Public hHook As Long
Per prima cosa si installa l'hook di sistema specificando
che è relativo alla tastiera.
'Il secondo parametro è l'indirizzo della callback, come
'definito nell'SDK, che riceve gli eventi di tastiera.
hHook = SetWindowsHookEx(WH_KEYBOARD, _
    AddressOf KeyboardProc, _
    App.hInstance, _
    App.ThreadID)
'La callback riceve l'id dell'hook di sistema, in wParam il
virtual-key code. lParam è un valore bit-wise a 32 bit che
ha vari significati in base ai bit a 1. Ad esempio o bit da 0 a
15 sono il numero di pressioni ripetute del tasto, il bit 31 è
lo stato di transizione (in pressione, in rilascio).
Function KeyboardProc(ByVal idHook As Long, _
    ByVal wParam As Long, _
    ByVal lParam As Long) As Long
    If idHook < 0 Then
        'Se l'id è un numero negativo, è necessario ritornare
        'subito il controllo alla procedura che deve ricevere
        'l'evento.
        KeyboardProc = CallNextHookEx(hHook, _
            idHook, wParam, ByVal lParam)
    Else
        'Si valutano i codici che interessano
        Select Case wParam
            Case xxx, yyy
                'Action code da inserire
                KeyboardProc = 1
                Exit Function
            Case nnn
                'Si valuta se è stato premuto anche Shift
                If GetKeyState(VK_SHIFT) And &HF0000000 Then
                    'Action code da inserire
                    KeyboardProc = 1
                    Exit Function
                End If
            Case Else
            '    NOP - il codice non interessa
        End Select
        'Si chiama la procedura che in origine doveva ricevere
        'l'evento. La callback deve sempre ritornare il valore
        ' che riceve da questa chiamata.
        KeyboardProc = CallNextHookEx(hHook, _
            idHook, wParam, ByVal lParam)
    End If
End Function
'In chiusura si rilascia l'hook impostato
hHook = UnhookWindowsHookEx(hHook)
hHook = 0

[...cut...]
Mi ha incuriosito molto quello che hai scritto su SetWindowsHookEx, per cui
sono andato a guardarmi sull'MSDN quest'API...
ho visto che puoi chiamarla con idHook = WH_CALLWNDPROC, in questo modo
sarebbe possibile effettuare un SubClassing di un'altra applicazione?
è una cosa che ho sempre desiderato, e a quanto ne so (poco) credo di aver
capito che il SubClassing tradizionale con un altro programma sarebbe
fattibile solo se la NewWindowProc è definita in una DLL *non* ActiveX (cioè
non fatta con VB, ma col C per esempio)
mi interesserebbe sapere se:
1) Effettivamente chiamando SetWindowsHookEx con WH_CALLWNDPROC
funzionerebbe
2) Passando come indirizzo della hook procedure la mia NewWindowProc
dichiarata come Public in un mio modulo
3) Passando come istanza dell'applicazione quella dell'applicazione che
voglio SubClassare, e come ThreadId sempre quello di quest'applicazione
se poi qualcuno l'ha già fatto mi piacerebbe sapere quali sono state le
difficoltà più grosse nella realizzazione (e naturalmente nel debug, visto
che in questi casi è praticamente inesistente di solito...)
grazie di ogni informazione
Faber

dichiarata come Public in un mio modulo
Da MSDN:
"lpfn
Pointer to the hook procedure. If the dwThreadId parameter is zero or
specifies the identifier of a thread created by a different process, the
lpfn parameter must point to a hook procedure in a dynamic-link library
(DLL). Otherwise, lpfn can point to a hook procedure in the code associated
with the current process."
...per cui mi sono risposto da solo, acc...
qualcuno ha qualche soluzione, caso mai avessi intenzione di SubClassare una
finestra non appartenente al mio processo?
(ovvero --> qualcuno l'ha già fatto e sarebbe così gentile da postarmi sia
il progetto della DLL in C sia il progetto VB che la usa?   :)     )
mi rendo conto di chiedere molto... ma io ci provo    ^__^
se potessi scrivere in HTML scriverei un GRAZIE in blu sz 58 !!!
Faber
P.S.: il mio indirizzo di posta è 
zann...@libero.it

 wrote in message 8anfct$17m$1...@nslave1.tin.it...


Appena leggi questa e-mail prova a contattarmi... ciao!!!!





> Appena leggi questa e-mail prova a contattarmi... ciao!!!!
Mi dispiace di non essermi fatto sentire prima; purtroppo sono
molto impegnato.
----[OT] mode on
Per favore, non inviare email con attachment se non mi
avverti prima; finiscono direttamente nel "tritarifiuti".
----[OT] mode off
In VB, non è possibile creare un hook esteso a tutte le finestre
di sistema, codificando per un eseguibile standard.
Occorre creare una DLL, come poi diceva giustamente Faber.
In teoria questa DLL si potrebbe fare anche in VB. Anche se
non è una libreria "standard" è comunque trattata diversamente
da un normale eseguibile. Il problema non è tanto effettuare il
trapping dei key code - questo viene sicuramente fatto - quanto
piuttosto restituire correttamente il controllo della tastiera alla
applicazione che originariamente doveva ricevere l'evento.
Mi riferisco in particolare alla funzione CallNextHookEx. Data
la "struttura" (i puristi chiudano un occhio) di una DLL Activex,
ho dei dubbi che questa funzione si comporti correttamente; penso
piuttosto che si generi un crash dell'applicazione per un difetto
di indirizzamento della memoria, tipo un GPF relativo al thread
interessato (i puristi chiudano anche l'altro occhio).
Un tentativo però si può fare, giusto per vedere il risultato.
Potresti trasportare il codice descritto nel precedente messaggio
in un modulo standard, creando due funzioni che eseguano il codice
relativo a SetWindowsHookEx e UnhookWindowsHookEx.
Public Sub HookProc()
   hHook = SetWindowsHookEx(WH_KEYBOARD, _
        AddressOf KeyboardProc, App.hInstance, 0)
End Sub
Public Sub UnhookProc()
   hHook = UnhookWindowsHookEx(hHook)
   hHook = 0
End Sub
Aggiungere poi al progetto un modulo di classe che abbia
due metodi, tipo
Public Function StartHook() As Boolean
   Call HookProc
   'Gestione errori
End Function
Public Function StopHook() As Boolean
   Call UnhookProc
   'Gestione errori
End Function
Non resta che compilare come DLL e provare il risultato.
(Occhio a come compili la DLL, rischi di trovarti mille
riferimenti ad Activex di versioni diverse)
Per provare basta creare un eseguibile standard che referenzi
la DLL Activex registrata e invocare i suoi metodi.
Auguri !