Il blog di Gianni Giaccaglini

Blog su VBA e VSTO
Gianni Giaccaglini

My Links

News

NB - V. anche gli ARTICOLI (in fondo a questa barra)
Solo quesiti validi a: giannigiac@tin.it
Il mio nuovo libro


La mia nipotina ELISA

Foto con dedica a ME di
Bill Gates giovanissimo
nei mitici anni 80!

Categorie Post

Categorie Articoli

Archivio

Immagini

Blog Stats

Minitastiera virtuale, contro spie e furti d'identità (spyware)

Mini tastiera virtuale con un foglio di lavoro

Antefatti

La storia inizia con la segnalazione da parte del collega Calogero Rifici della sua ottima implementazione di una tastiera virtuale. Per saperne di più, anche sul tema scottante della necessità di difendersi contro gli hacker spioni (che, a quanto sembra, arrivano a intercettare i tasti da noi battuti!, rubandoci password e altro) rimando doverosamente all’ottimo e godibilissimo post del Calogero, detto Calo:

http://blog.shareoffice.it/calogerorifici/articles/8482.aspx

Ci informa Calo: “Uno spyware è un tipo di software che raccoglie informazioni riguardanti l'attività online di un utente (siti visitati, acquisti eseguiti in rete, username, Password e via di seguito) senza il suo consenso, trasmettendole tramite Internet ad un'organizzazione che le utilizzerà per trarne profitto, tipicamente attraverso l'invio di pubblicità mirata. Ma i problemi più grossi si hanno quando qualcuno riesce a carpire la nostra username e la nostra password, per quel determinato servizio.”

Tutti potranno ammirare il capodopera del Nostro, una bellissima e scenografica UserForm irta di pulsanti di comando (un’ottantina!) in maggioranza destinati a imitare uno dei tasti della tastiera normale e ad inserirli in un oggetto DataObject, sfruttandone i metodi SetText , che acquisisce materiale testuale nel DataObject, e PutInClipboard, che lo riversa negli Appunti (alias Clipboard). In tal modo l’utente può successivamente incollare ovunque vuole la roba ivi depositata, al riparo dei dannati hacker.

Per far capire la faccenda ai frettolosi, ecco una banale routinetta insultante applicata a una semplice UserForm con una TextBox1 (N.B. con proprietà Multiline impostata) e un solo CommandButton1:

Private Sub CommandButton1_Click()

  Dim i As Currency, Testo As String

  Const Insulto As String = "Vaffanbagno "

  Dim TestoDaIncoll As DataObject

  Set TestoDaIncoll = New DataObject

  Testo = Insulto & "numero 1" & vbLf

  For i = 2 To 10

    Testo = Testo & Insulto & "numero " & i & vbLf

  Next

  TextBox1.Text = Testo & "Ti bastano dieci insulti?"

  With TestoDaIncoll

    .SetText TextBox1.Text 'anche Testo andrebbe bene

    .PutInClipboard

  End With

  'Unload UserForm1 'istruzione eventuale?

End Sub

Nottetempo ho fatto un sogno: perché non emulare una minitastiera virtuale con un foglio di lavoro Excel? Questo per due motivi:

1)     Sono pigro e non ho tempo né voglia di creare enormi UserForm…

2)     C’è già il lavoro del Calo, non vale certo la pena di rifarlo! Va anche aggiunto che la sua UserForm è più generale e potrebbe essere adottata in altri mondi Office (Word, Outlook…).

Nota – Anzi gli suggerirei di cimentarsi col Visual Basic .NET o anche solo VB 6, ottenendo così un’utility eseguibile, utilizzabile ovunque.

La mia tastierucola virtuale

Si presenta sul Foglio 1 del modello come segue:

!

"

$

%

&

/

\

'

< 

> 

@

#

 

1

2

3

4

5

6

7

8

9

0

=

?

!

BACKSPACE

q

w

e

r

t

y

u

I

O

p

à

è

ì

 

Q

W

E

R

T

Y

U

I

O

P

=

È

!

INVIO

a

s

d

f

g

h

j

k

L

o

ò

ù

(

A

S

D

F

G

H

J

K

L

O

Ò

Ù

)

 

> 

z

x

c

v

b

n

M

;

:

_

#

§

 

< 

Z

X

C

V

B

N

M

,

.

-

|

*

 

 

 

 

Barra spaziatrice

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Dimenticavo: il file si trova al link seguente:

http://www.shareoffice.it/Download/MiniTastieraVirtuale.xls

È quasi inutile dire che ho preferito limitarmi alle lettere, cifre e segni speciali più usati, consapevole che emulare tasti funzioni F1-F12, Ctrl e Alt avrebbe reso il lavoro troppo complesso (ma poi a che scopo? Qui vogliamo solo inserire caratteri, no?). In compenso ho previsto lettere sia minuscole che maiuscole, evitando così la noia del tasto Shift…

L’idea? Molto semplice: sfruttare l’evento SelectionChange dell’oggetto Worksheet in modo che il (singolo!) carattere presente nella cella cliccata venga accodato. Accodato a cosa? Ma al testo di una casella di testo ottenibile con la barra Disegno, non riportata sopra, ma ben in vista sotto alla zona “caratteriale”. In tal modo cliccando sulle celle-tasto si può vedere il testo progressivo.

I nomi di celle e zone e della casella. Eccoli, affiancati dai rispettivi riferimenti (tutti sul Foglio1) nonché da una spiega sintetica delle funzioni espletate:

Tastiera

$C$7:$O$14

L’intervallo dei tasti. Notare la presenza di minuscole e maiuscole

INVIO

$P$10

Cella sulla destra, che emula il tasto omonimo

BACKSPACE

$P$8

Idem come sopra, a emulazione del tasto che cancella a ritroso

Barra_spaziatrice

$F$15

Idem come sopra, a emulazione… beh il nome è autoesplicativa, no?

Riposo

$B$7

v. più avanti

CellaDepTesto

$AF$54

v. più avanti

Casella

//

Nome affibbiato alla (unica) casella di cui sopra

Nota – Per l’esattezza “Tastiera” e “Barra_spaziatrice” sono fuse con celle viciniori (per l’estetica, più che altro.

Domandina per i più brevetti: a cosa servirà mai la cella “Riposo” ? Lo potranno scoprire esaminando il codice che sto per riportare. Fin d’ora posso ricordare che l’evento Change si scatena solo quando il tasto pigiato cambia. A buon intenditor…

Il codice sul modulo Foglio1

Prima di esaminare la macro maggiore, una premessa: il foglio di lavoro è protetto, mediante il comando manuale Strumenti > Protezione > Proteggi foglio sottinteso: corrente), cui in VBA corrisponde il metodo Protect dell’oggetto Spreadsheet, mentre Unprotect lo sprotegge (come nel comando manuale Strumenti > Protezione > Rimuovi protezione foglio). Questo perché? Ma per impedire che le celle della tastiera vengano modificate da qualche sprovveduto. Ne consegue qualche ammattimento nelle macro, in quanto si constata la necessità di Unprotect quando si vogliono aggiungere caratteri alla “Casella”.

Nota – Infatti la protezione del foglio si estende alle forme e oggetti in esso incorporati.

Già che ci sono, anticipo una trovatine dell’ultim’ora, relativa all’evento doppio clic, la cui routine trovasi nel modulo Foglio1:

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)

  Cancel = True 'Evita l'interferenza del doppio clic!

End Sub

Nota – La motivazione è già riassunta nella nota. Ma chi saprebbe approfondirla?

Ma ecco il codice contenuto nel modulo Foglio1:

Private Sub Worksheet_SelectionChange(ByVal Target As Range)

  If Target.Address = Range("Riposo").Address Then Exit Sub

  Me.Unprotect

  If Target(1).Address = Range("Barra_spaziatrice").Address Then

    Me.TextBoxes(1).Text = Me.TextBoxes(1).Text & Chr(32)

    Esci

  End If

  If Target(1).Address = Range("INVIO").Address Then

    Me.TextBoxes(1).Text = Me.TextBoxes(1).Text & vbLf

    Esci

  End If

  Dim Lung As Integer

  If Target(1).Address = Range("BACKSPACE").Address Then

    With Me.TextBoxes(1)

      Lung = Len(.Text)

      .Text = Left(.Text, Lung - 1)

    End With

    Esci

  End If

  If Intersect(Target, Range("Tastiera")) Is Nothing Then

    'Seleziona il primo tasto di “Tastiera” se l’utente clicca fuori

    Range("Tastiera")(1).Select

    Exit Sub

  End If

  'Accoda il carattere della cella cliccata (Target) alla Casella

  Me.TextBoxes(1).Text = Me.TextBoxes(1).Text & Target.Text

  Esci

End Sub

 

Private Sub Esci()

  Range("Riposo").Activate

  Me.Protect

  End

End Sub

Avete esaminato le istruzioni? Allora sarete, spero, in grado di rispondere al precedente quesito: l’istruzione Esci, che richiama l’omonima Sub, attiva la cella “Riposo” ogni volta che l’utente ha cliccato una cella della “Tastiera”, consentendogli così di ripetere il clic sulla cella precedente (altrimenti testi come “Tutti matti” verrebbero inseriti come “Tuti mati”, per la gioia di “tuto” l Nord-Est ma la disperazione del Tommaseo & successori.

A questo punto penso che non occorra aggiungere commenti a quelli già presenti nella routine. Dico solo che (ovviamente) Me.TextBoxes(1) corrisponde alla casella incorporata, unico membro dell’insieme TextBoxes (Me equivale a Foglio1 e andava bene pure Me.TextBoxes(“Casella”, se sbaglio correggetemi).

Nota – Insiemi come TextBoxes, Arcs  ecc. sono considerati obsoleti. Ora si parla solo di oggetti Shape ma questi arnesi sorpassati a volta sono più chiari, perché godono di proprietà specifiche, mentre alle Shape, generiche, si applicano sulla carta più proprietà, alcune delle quali però falliscono con questo o quella forma particolare.

Mi fermo qui. Capire come funzionano i casi della barra spaziatrice, di Invio e Bbackspace lo lascio per esercizio.

E l’istruzione Cancel = True della routine d’evento doppio clic? Come tutti avranno scoperto, togliendola salta fuori un messaggio di protesta e, peggio ancora, il funzionamento corretto è alterato, anche se si ripristina insistendo col clic (semplice).

Il codice sul modulo Modulo1

Si tratta di due routine collegate a due omonimi pulsanti “classici” di Excel, ossia ottenuti con la barra strumenti Moduli, posti sopra alla tastierina virtuale. Per la precisione, la seconda è una precedente versione, poi indicherò quella di fatto adottata.

Sub Inizio()

  With Foglio1

    .Unprotect

    'svuota la Casella di testo

    .TextBoxes(1).Text = ""

    .Protect

  End With

End Sub

 

Sub Appunti()

  With Foglio1

    .Unprotect

    .Shapes("Casella").Select

    Range("CellaDepTesto") = Selection.Characters.Text

    Range("CellaDepTesto").Copy

    '.Protect ELIMINATO! Perché annulla la copia (chi sa dire perché?)

  End With

  MsgBox "Ora il testo della casella è negli Appunti" & vbLf _

        & "Puoi incollarlo altrove con Ctrl+V", vbInformation, "Ricorda!"

  'Soluzione brute force, che chiude il modello, insalutato utente

  'Miglioratela, se vi interessa...

 

  Application.DisplayAlerts = False 'Annulla ogni avviso

  'Inganna Excel, facendogli credere che il modello è stato salvato

   With ThisWorkbook

     .Saved = True

     .Close

   End With

End Sub

La prima Sub si spiega da sé. La seconda, per farla breve, sfrutta una cella remota di nome “CellaDepTesto” per depositarvi il contenuto della Casella. I motivi sono due:

  • Il pur potente oggetto DataObject purtroppo non si applica a un Foglio1, Foglio2 ecc.;
  • Dio sa perché, un’istruzione (che parrebbe logica!) del tipo seguente:
    Foglio1
    TextBoxes(1).Text.Copy dà errore, idem quest’altra:
    Selection.Characters.Text.Copy, preceduta dalla selezione della casella.

Nota - Non c’è niente da fare, il metodo Copy, che dovrebbe riempire gli appunti non si applica agli oggetti predetti.

Per questo ho ripiegato – sempre nella vecchia versione - sulle istruzioni che qui ripeto, per comodità:

    .Shapes("Casella").Select

    Range("CellaDepTesto") = Selection.Characters.Text

Con le quali si riesce (ma che fatica è stata, trovarle!) a mettere il testo della Selection, ossia della casella preliminarmente selezionata, nella cella remota (fuori della vista) battezzata “CellaDepTesto”.

I (mezzi) guai non finiscono, a causa dell’istruzione successiva: Range(“CellaDepTesto”).Copy

Questo a causa dei (dannati) trattini ruotanti attorno a celle copiate, ereditati da Lotus 1-2-3 per DOS!

Nota - Assenti in qualunque altro programma Windows, inclusa la poco fortunata versione Windows di Lotus 1-2-3, ove un’istruzione analoga lascia iil materiale negli Appunti, senza altre storie…

Per questo motivo ho implementato – sempre nella vecchia versione - le istruzioni conclusive, che brutalmente chiudono il modello avvertendo l’utente che da questo momento può usare Ctrl+V (ad esempio dopo aver aperto un documento Word o un qualche modulo Web “riservato”).

La cosa è scontata, l’inconveniente è il dover ri-caricare il modello per un altro lavoro (ma in fondo una tastiera virtuale di regola serve, al più, una volta al giorno…

La versione di Appunti adottata. Pensa e ripensa, e malgrado io sia tutt’altro che un… benpensante, ho avuto una pensata (pensate voi):

Sub Appunti()

  With Foglio1

    .Unprotect

    .Shapes("Casella").Select

    Range("CellaDepTesto") = Selection.Characters.Text

    Range("CellaDepTesto").Copy

    '.Protect DA ELIMINARE! Perché annulla la copia...

  End With

  Foglio2.Activate

  Range("D1").Select

  MsgBox "Ora il testo della casella è negli Appunti" & vbLf _

        & "Puoi incollarlo altrove con Ctrl+V", vbInformation, "Ricorda!"

End Sub

Come si scopre usando il modello, la “CellaDepTesto” si trova nel Foglio2, che stavolta, al termine, viene attivato selezionando la cella D1, posta sopra celle esplicative opportune. Ossia grossomodo (notare i trattini attorno alla cella gialla):

Se nella cella gialla qui sotto vedi trattini ruotanti, vuol dire che il testo digitato si trova negli Appunti.

Di conseguenza, se ti interessa copiarlo altrove, esegui i passi seguenti senza selezionare NULLA:

1. apri un altro documento (Word, Excel ecc.) o una pagina Web;

2. seleziona la posizione, area, cella o quant'altro che ti interessa;

3. premi Ctrl+v (o scegli Modifica > Incolla) per incollarvi il testo degli Appunti

 

Quanto è bella giovinezza, che si fugge tuttavia!
Chi vuol esser lieto sia
Del diman non v'ha certezza...

 

Se invece non vedi (o hai fatto sparire i trattini) e ti interessa ugualmente il materiale della cella gialla,

selezionala, poi premi Ctrl+c per copiarne manualmente il contenuto negli Appunti

quindi procedi coi precedenti passi 2 e 3.

 

Ritorna alla tastiera

Non credo che, qui giunti, occorrano altre spiegazioni, salvo una precisazione: “Ritorna alla tastiera” è un hyperlink locale che riporta al Foglio 1, cella “Riposo”, per un nuovo giro virtual-digitatorio . E va da sé che con questa ideuzza si evita la chiusura di Excel.

Osservazione finale (un po’ azzardata?). Con questo procedimento si potrebbe realizzare una qualche tastiera stenografica comprendente non solo lettere ma anche sillabe e frasi fatte. Verrebbe troppo estesa e cliccarci qua e là col mouse poco veloce? Le discussioni sono aperte.

?>

posted on mercoledì 20 dicembre 2006 12.14