|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: Mar 2008
Città: Milano; 9 Vendite concluse -> Wilde; emmepi; Homerj81; cos1950; mariotanza; Benia; grigor; alekia; ARG0
Messaggi: 11160
|
[VB.Net] Problema con API
Ciao a tutti. Ho un problema con l'intercettazione dgli input da tastiera dalle API di windows. Per registrare uso queste righe di codice:
Codice:
Public Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer
---------------------------------------
Public valoreRitorno As Integer = 0
---------------------------------------
Private Sub tmrInputTasti_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tmrImputTasti.Tick
'Controllo input da tatiera
Dim i As Integer
For i = 0 To 300
valoreRitorno = GetAsyncKeyState(i)
If valoreRitorno = -32768 Then
ListBox1.Items.Add(i & " -> " & Chr(i))
Select Case (i)
Case 97
btn1.PerformClick()
Case 49
btn1.PerformClick()
Case Else
'...
End Select
End If
Next i
End Sub
Il tick del timer è impostato a 10ms ed è enabled. Nel Form Load ho impostato l'avvio del timer ( tmrInputTasti.Start() ) Il problema è che non funziona... |
|
|
|
|
|
#2 |
|
Senior Member
Iscritto dal: Mar 2008
Città: Milano; 9 Vendite concluse -> Wilde; emmepi; Homerj81; cos1950; mariotanza; Benia; grigor; alekia; ARG0
Messaggi: 11160
|
Ho trovato il problema: è la compilazione a 64bit. Il problema non si presenta impostando x86 ma si presenta con "Any CPU" e "x64". Come faccio per usare la funzione a 64bit??
|
|
|
|
|
|
#3 |
|
Senior Member
Iscritto dal: Mar 2008
Città: Milano; 9 Vendite concluse -> Wilde; emmepi; Homerj81; cos1950; mariotanza; Benia; grigor; alekia; ARG0
Messaggi: 11160
|
UP!
|
|
|
|
|
|
#4 |
|
Senior Member
Iscritto dal: Dec 2004
Messaggi: 3210
|
Non avendo gran dimestichezza con i S.O. 64bit, la prima domanda è : sicuro che in Win7 64 ci sia una user32.dll ?
Quasi certamente, sì. Il VS da cui sviluppi/compili è su Win-32 o su Win7-64 ? Infine, mi pare di aver capito che il tuo compilato X86, come lecito aspettarsi, funziona sia su 32 che su 64, mentre quello che mi suona strano è l'AnyCpu che da problemi... Dal momento che la stragrande maggioranza del software applicativo che c'è in giro è a 32bit ( da quel che so, solo chi scrive antivirus, drivers ecc... è praticamente costretto a fare 2 versioni separate... ), e sarà così per un bel pezzo ancora, il mio umile consiglio è : mettiti l'animo in pace e compila per X86...
|
|
|
|
|
|
#5 | |
|
Senior Member
Iscritto dal: Mar 2008
Città: Milano; 9 Vendite concluse -> Wilde; emmepi; Homerj81; cos1950; mariotanza; Benia; grigor; alekia; ARG0
Messaggi: 11160
|
Quote:
Cmq grazie! |
|
|
|
|
|
|
#6 | |
|
Senior Member
Iscritto dal: Dec 2004
Messaggi: 3210
|
Quote:
Qualche tempo fa avevo letto alcune statistiche sulla diffusione dei S.O. a 64 bit, e mi è sembrato un discorso marginale. C'è ancora molta gente che, se si parla di WinXP, l'unico che conosce è il 32, mentre non sospetta ne esista uno a 64. Per quanto riguarda Vista, avevo letto che tra gli utenti ad averlo accolto con maggior freddezza, c'erano proprio quelli che del pc ne fanno uso professionale, figuriamoci poi Vista 64... Sulla tua ultima domanda, direi che è così, nel senso che se compili x86 hai la certezza che giri dappertutto, con x64 su S.O. 64 sfrutterà i vantaggi della piattaforma, e cmq l'exe prodotto è diverso, tanto che se provi ad seguirlo su WinXP 32 non gira. La spiegazione che forse mi convince di più, al momento è questa : In the wonderful world of .NET development, applications and assemblies can be compiled to target various platforms. By default, applications and assemblies are compiled as Any CPU in Visual Studio. In this scenario, the CLR will load the assembly as whatever the default target is for the machine it is being executed on. For example, when running an executable on an x64 machine, it will be run as a 64-bit process. Visual Studio also provides for 3 specific platform targets: x86, x64 and Itanium (IA-64). When building an executable as a specific target, it will be loaded as a process of that type. For example, an x86-targeted executable run on an x64 machine will run as a 32-bit process using the 32-bit CLR and WOW64 layer. When assemblies are loaded at runtime, they can only be loaded by a process if their target matches that of the hosting process, or it is compiled as Any CPU. For example, if x64 were set as the target for an assembly, it can only be loaded by an x64 process. |
|
|
|
|
|
|
#7 | |
|
Senior Member
Iscritto dal: Mar 2008
Città: Milano; 9 Vendite concluse -> Wilde; emmepi; Homerj81; cos1950; mariotanza; Benia; grigor; alekia; ARG0
Messaggi: 11160
|
Quote:
Lasciando perdere l'utente medio, il 64bit si sta iniziando a diffondere anche in ambito professionale. Si pensi a Photoshop Extended CS4 che esiste anche in versione 64bit. I software Autodesk esistono in doppia versione e anche i software di minore importanza dispondogo del corrispettivo a 64bit. Anche WinRAR c'è a 64bit... Sono d'accordo che non è molto diffuso cmq muoversi in quella direzione trovo sia una buona cosa. Non sono uno sviluppatore però, se posso dire la mia, non capisco come mai non si facciano SW a 64bit: su VB basta una stupida spunta e cambiare 4 righe di codice... Saresti così gentile da spiegarmi come funziona la procedura paso passo che così magari riesco a capire come convertirla a 64bit? (Questa la scrivesti tu, sempre per me, qualche mese fa In generale la capisco ma ci sono alcuni passaggi che ho scritto proprio senza capirli... Codice:
Public Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer 'vKey che cosa mi rappresenta? User32 si chiama 32 perchè siamo su 32bit, no? Su 64bit come si chiama??? Perchè vKey è Long??? I tasti non sono così tanti...
---------------------------------------
Public valoreRitorno As Integer = 0
---------------------------------------
Private Sub tmrInputTasti_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tmrImputTasti.Tick
'Controllo input da tatiera
Dim i As Integer
For i = 0 To 300 'Perchè il tutto è in un for???
valoreRitorno = GetAsyncKeyState(i)
If valoreRitorno = -32768 Then 'Perchè -32768??32678 è il massimo per gli Integer, se restituisco in Int64 sarebbe 65K e rotti? Da cosa deriva quel -32678?
ListBox1.Items.Add(i & " -> " & Chr(i))
Select Case (i)
Case 97
btn1.PerformClick()
Case 49
btn1.PerformClick()
Case Else
'...
End Select
End If
Next i
End Sub
|
|
|
|
|
|
|
#8 |
|
Senior Member
Iscritto dal: Dec 2004
Messaggi: 3210
|
Sì, ricordo, anche se non penso di averti suggerito io quel For i = 0 To 300... Bisognerebbe controllare solo i valori di interesse...
Comunque : 1. Che io sappia le cose sui vari Win 64 stanno così : di user32.dll ce n'è una in XP32, mentre a quanto so io ce ne sono 2, ad es. in Vista64, la versione a 64 bit di user32, si chiama sempre user32.dll, e sta in C:\WINDOWS\System32\ , mentre la versione a 32 bit ( sempre user32.dll ) starebbe in C:\WINDOWS\SysWOW64\. Ma queste sono cose che devi verificare meglio tu, in quanto stai usando un Win64... In ogni caso se cerchi una "user64.dll" temo rimarrai deluso. Il perchè di tutto ciò lo sa solo Iddio e qualcuno alla MS, personalmente è solo uno tra i molti motivi che mi hanno fatto cestinare Vista. Non so se in Win7 abbiano imparato la lezione... Lo proverò quando uscirà in versione finale... 2. vKey ecc... : la confusione deriva dal fatto che probabilmente ti avevo postato un codice preso da VB6 e riadattato velocemente per VB.NET. In VB6 Integer è un intero con segno da 2 byte, mentre Long è a 4 byte. Perciò Integer e Long in VB.NET non corrispondono. Sono più grandi. E Long in VB.NET è un int64, un tipo di intero che in VB6 non esiste. La signature corretta in VB.NET è questa : Codice:
Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Int32) As Int16 Codice:
Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Integer) As Short Codice:
Public Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer 3. For : il For serve a controllare un range di tasti in un intervallo contiguo, per evitare di fare una lunga serie di If... 4. In conclusione ti riformulo l'esempio in modo forse più comprensibile e sicuramente più snello e adatto a VB.NET : poniamo debba intercettare tutti i tasti alfanumerici + 3 tasti speciali : Codice:
Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Int32) As Int16
Private vK As Int32 = 0
Private Const vOk As Int16 = -32767
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
'tasti ordinari
For Me.vK = 48 To 57 ' 0123456789
If GetAsyncKeyState(vK) = vOk Then ListBox1.Items.Add(Chr(vK))
Next vK
For Me.vK = 65 To 90 ' ABCDEFGHIJKLMNOPQRSTUVWXYZ
If GetAsyncKeyState(vK) = vOk Then ListBox1.Items.Add(Chr(vK))
Next vK
'tasti speciali
'F12
If GetAsyncKeyState(Keys.F12) = vOk Then ListBox1.Items.Add("F12")
'Right-CTRL
If GetAsyncKeyState(Keys.RControlKey) = vOk Then ListBox1.Items.Add("R-CTRL")
'NumPad 5
If GetAsyncKeyState(Keys.NumPad5) = vOk Then ListBox1.Items.Add("NumPad 5")
End Sub
http://www.developer.com/net/vb/arti...0926_2193301_1 |
|
|
|
|
|
#9 | |
|
Senior Member
Iscritto dal: Mar 2008
Città: Milano; 9 Vendite concluse -> Wilde; emmepi; Homerj81; cos1950; mariotanza; Benia; grigor; alekia; ARG0
Messaggi: 11160
|
Quote:
Grazie mille per la funzione VB.Net dei tasti, ora è molto più chiara... un po' meno quella dei tipi di variabile anche perchè non ho mai sentito di variabili short... - Int -> Short (Int16) - Long -> Integer (Int32) C'è forse uno shift dei tipi? Ma esiste una differenza tra Int64 e Long? Se esistono gli short, perchè vengono usati più spesso gli integer? Più che gli imput da tastiera ora come ora mi interessano le varie interazioni con l'ambiente di sistema (user32....) anche se prima forse dovrei studiarmi i database PS. Ho notato che un imput da numpad (es tasto 5) da un numero di imput differente rispetto ai numeri "sopre le lettere" (sempre per il numero 5, ad es), ma a lato pratico se schiaccio 5 sia sul tastierino che non l'applicazione risponde nel medesimo modo.... Strano... (Num Lock attivo) |
|
|
|
|
|
|
#10 | ||
|
Senior Member
Iscritto dal: Dec 2004
Messaggi: 3210
|
Quote:
- Short = Int16 signed - Integer = Int32 signed - Long = Int64 signed VB6 : - Short > N.D. - Integer > Int16 signed - Long > Int32 signed Inoltre VB.NET ha i tipi Integer unsigned ( che ti permettono di raddoppiare il valore max, sul semiasse positivo ) : UShort, UInteger, ULong, che sono assenti in VB6. Se vuoi farti un'idea dei valori estremi raggiungibili dai vari tipi, basta leggerne MaxValue e MinValue : Codice:
Dim a As ULong
MsgBox(a.MinValue & " > " & a.MaxValue)
Nella vita reale, già un Integer è sovrabbondante, un ULong è "cosmico" ( fai il MaxValue su ULong e ottieni : 18'446'744'073'709'551'615 ) Quote:
In ogni caso puoi anche gestire il NumLock : Codice:
'NumLock
If GetAsyncKeyState(Keys.NumLock) = vOk Then
If My.Computer.Keyboard.NumLock = True Then
ListBox1.Items.Add("NumLock ON")
Else
ListBox1.Items.Add("NumLock OFF")
End If
End If
|
||
|
|
|
|
|
#11 | |
|
Senior Member
Iscritto dal: Mar 2008
Città: Milano; 9 Vendite concluse -> Wilde; emmepi; Homerj81; cos1950; mariotanza; Benia; grigor; alekia; ARG0
Messaggi: 11160
|
Quote:
|
|
|
|
|
|
|
#12 |
|
Senior Member
Iscritto dal: Dec 2004
Messaggi: 3210
|
|
|
|
|
|
|
#13 | |
|
Senior Member
Iscritto dal: Mar 2008
Città: Milano; 9 Vendite concluse -> Wilde; emmepi; Homerj81; cos1950; mariotanza; Benia; grigor; alekia; ARG0
Messaggi: 11160
|
Quote:
Codice:
....
case 80
txtBox1.text = txtBox1.text + "5"
....
|
|
|
|
|
|
|
#14 | |
|
Senior Member
Iscritto dal: Dec 2004
Messaggi: 3210
|
Quote:
Codice:
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
If GetAsyncKeyState(53) = vOk Then ListBox1.Items.Add("5")
End Sub
. Sente solo il tasto 5, mentre non sente il NumPad5... Non so se è questo che intendevi... |
|
|
|
|
|
|
#15 | |
|
Senior Member
Iscritto dal: Mar 2008
Città: Milano; 9 Vendite concluse -> Wilde; emmepi; Homerj81; cos1950; mariotanza; Benia; grigor; alekia; ARG0
Messaggi: 11160
|
Quote:
Codice:
....
For i=0 To 300
...
Case 53 '5
btnOK.PerformClick()
Case 101 'NumPad 5, NumLock Enable
btnOK.PerformClick()
...
Codice:
....
For i=0 To 300
...
Case 53 '5
btnOK.PerformClick()
...
Altra cosa interessante: se premo il numpad5 con il num lock attivato nella listbox utilizzata per il debug compare 101 -> e invece di 101 -> 5. Perchè? |
|
|
|
|
|
|
#16 |
|
Senior Member
Iscritto dal: Dec 2004
Messaggi: 3210
|
Allora, vediamo di capirci. Torniamo al tuo codice iniziale e proviamo a gestire solo i due tasti, 5 e NumPad5.
Anzitutto il tuo valore di 300 è inutile, in quanto il parametro vKey è destinato a contenere valori da 0 a 255, come espressamente dichiarato nella documentazione MSDN della GetAsyncKeyState : vKey [in] Specifies one of 256 possible virtual-key codes Perciò mettiamo di avere questo codice, nel Timer : Codice:
Dim i As Integer
For i = 0 To 255
valoreRitorno = GetAsyncKeyState(i)
If valoreRitorno = -32768 Then
Select Case (i)
Case 53 'Tasto 5
ListBox1.Items.Add("5")
Case 101 'NumPad 5
ListBox1.Items.Add("5")
Case Else
'...
End Select
End If
Next i
Mentre il codice seguente, eliminando la gestione del 101, NO. : Codice:
Dim i As Integer
For i = 0 To 255
valoreRitorno = GetAsyncKeyState(i)
If valoreRitorno = -32768 Then
Select Case (i)
Case 53 'Tasto 5
ListBox1.Items.Add("5")
Case Else
'...
End Select
End If
Next i
Infine vorrei fare chiarezza sul discorso del vKey. vKey NON è il codice ASCII della lettera associata al tasto premuto. Esiste una corrispondenza tra codici vKey ( Virtual-Key Codes ) della tastiera, e tabella ASCII su tutti i caratteri alfanumerici, la spacebar, più pochi altri tasti "standard". In questo caso solamente ha senso usare quel For e farsi ritornare la lettera/numero/simbolo del tasto premuto con la funzione Chr(). Per tutti gli altri casi ( tasti funzione, tasti NumPad ecc... ) i codici vKey e Ascii non corripsondono più, e infatti se si decide di costruire un vero e proprio keylogger usando GetAsyncKeyState, si dovrà creare una casistica completa, non basata sulla tabella Ascii, ma sulla tabella dei Virtual-Key Codes : http://msdn.microsoft.com/en-us/libr...40(VS.85).aspx Fortunatamente il buon VB ha lo spacename My. e in più l'Enum Keys. grazie ai quali il lavoro è notevolmente facilitato ( niente gestione diretta dei valori esadecimali delle Virtual-Key Codes ). Quindi, in conclusione, quando mi avevi chiesto un buon sistema per mappare alcuni tasti alfa (A, B, C) la risposta fu naturalmente GetAsyncKeyState(), perchè senza spendere fiumi di codice su hooks di basso livello, con tre righe potevi risolvere. Chiaro che adesso se ti vuoi allargare e mappare tutta la tastiera dovrai andare ben oltre quel semplice For... Spero di essere stato chiaro. |
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 12:33.












. Sente solo il tasto 5, mentre non sente il NumPad5... Non so se è questo che intendevi...








