Sunteți pe pagina 1din 23

Capitolul 5.

Tastatura
Dei Windows accept i mouse-ul ca dispozitiv de
intrare, tastatura deine nc poziia principal

Tastatura nu poate fi tratat ca un dispozitiv de


intrare independent de celelalte funcii ale
programului. De exemplu, programele rspund
deseori la intrrile de la tastatur afind
caracterele introduse n zona client a ferestrei.
Astfel, manipularea intrrilor de la tastatur i
afiarea textului trebuie s fie tratate mpreun.
Tastatura elemente de baz
Programul afl" despre apsarea unor taste prin
intermediul mesajelor care ajung la procedura de fereastr.
atunci cnd utilizatorul apas i elibereaz tastele,
driverul de tastatur transmite sistemului de operare
informaiile legate de aciunile asupra tastelor.
Windows salveaz aceste aciuni (sub form de mesaje)
n coada de ateptare a sistemului.
Mesajele de la tastatur sunt apoi transferate n coada
de mesaje a programului cruia i aparine fereastra ce
deine cursorul de intrare".
Programul distribuie mesajele procedurii de fereastr
corespunztoare.
Motivul acestui proces n dou etape este legat de
sincronizare.
Windows trimite programelor opt tipuri de mesaje
O parte a sarcinii de manipulare a tastaturii const n a ti ce
mesaje sunt importante.
Ignorarea tastaturii
Programele nu trebuie s reacioneze la toate mesajele de la
tastatur. Multe funcii ale tastaturii sunt tratate chiar de
Windows. De exemplu, putei s ignorai apsrile de taste
legate de funcii sistem.
Acceleratori" pentru opiunile de meniu folosite mai
frecvent - combinaii de taste funcionale - sau alte taste
corespunztoare unor caractere - cu tasta Ctrl.
Casetele de dialog au i ele o interfa cu tastatura, dar
programele, n general, nu trebuie s monitorizeze tastatura
ct timp este activ o caset de dialog.
Interfaa cu tastatura este manipulat de Windows i acesta
trimite programului mesaje prin care i comunic efectele
tastelor apsate.
Cursorul de intrare
Tastatura trebuie s fie partajat de toate aplicaiile rulate
simultan. Unele aplicaii pot avea mai multe ferestre, iar tastatura
trebuie s fie partajat de toate ferestrele din cadrul aceleiai
aplicaii. Atunci cnd este apsat o tast, o singur fereastr
trebuie s primeasc mesajul privind apsarea tastei respective.
Fereastra care primete acest mesaj este fereastra care deine
cursorul de intrare" (input focus").

Conceptul cursorului de intrare este strns legat de conceptul de


fereastr activ". Fereastra care deine cursorul de intrare este
fie fereastra activ, fie o fereastr descendent a ferestrei active.

Ferestrele descendent (butoanele de apsare, butoanele radio,


casetele de validare, barele de derulare, casetele de editare i
casetele list) nu sunt niciodat ferestre active. Dac o fereastr
descendent deine cursorul de intrare, atunci fereastra activ este
fereastra printe.

O procedur de fereastr poate s afle cnd are cursorul de


intrare prin interceptarea mesajelor WM_SETFOCUS i
WM_KILLFOCUS. Mesajul WM_SETFOCUS indic faptul c
fereastra primete cursorul de intrare (input focus), iar mesajul
WM_KILLFOCUS - c fereastra pierde cursorul de intrare.
Acionri de taste i caractere
Mesajele privind tastatura fac diferena ntre keystrokes"
i caractere". Aceste noiuni sunt legate de cele dou
moduri n care putei s privii tastatura.
n primul rnd, tastatura este o colecie de taste. Tastatura
are o singur tast A; apsarea tastei A este o acionare de
tast, iar eliberarea tastei A este tot o acionare de tast.
Tastatura este n acelai timp i un dispozitiv de intrare
care genereaz caractere afiabile. Tasta A poate s
genereze mai multe caractere, n funcie de starea tastelor
Ctrl, Shift i Caps Lock.
Pentru acionrile de taste care genereaz caractere
afiabile, Windows trimite programului att mesaje pentru
acionarea de taste, ct i mesaje pentru caractere.
Unele taste nu genereaz caractere. Astfel de taste sunt
Shift, tastele funcionale, tastele de deplasare i tastele
speciale, precum Insert i Delete. n cazul acestor taste,
Windows genereaz numai mesaje pentru acionari de
taste.
Mesaje pentru acionri de taste
Atunci cnd apsai o tast, Windows insereaz n coada de ateptare a
ferestrei care deine cursorul de intrare un mesaj WM_KEYDOWN sau un mesaj
WM_SYSKEYDOWN. Atunci cnd eliberai fasta, Windows insereaz n coada de
ateptare a ferestrei un mesaj WM_KEYUP sau un mesaj WM_SYSKEYUP

Tasta a fost apsat Tasta a fost eliberat


Tast obinuit WM_KEYDOWN WM_KEYUP
Tast de sistem WM_SYSKEYDOWN WM_SYSKEYUP

De obicei, mesajele de apsare i de eliberare a tastei sunt trimise n pereche.


Ca toate mesajele trimise prin coada de ateptare, mesajele pentru acionri
de taste conin informaii de timp. Putei s obinei momentul relativ n care a
fost apsat sau eliberat o tast apelnd funcia GetMessageTime
Taste obinuite i taste de sistem
Particula SYS" din mesajele WM_SYSKEYDOWN i
WM_SYSKEYUP - taste apsate n combinaie cu tasta Alt.
Aproape toate mesajele care afecteaz fereastra programului
trec mai nti prin procedura de fereastr. Windows
prelucreaz aceste mesaje numai dac le retransmitei
funciei DefWindowProc.
Dac n procedura de fereastr adugai urmtoarele linii:
case WM_SYSKEYDOWN :
case WM_SYSKEYUP :
case WM_SYSCHAR :
return 0 ;
dezactivai toate operaiile legate de combinaiile Alt+tast
Mesajele WM_KEYDOWN i WM_KEYUP sunt generate, de
obicei, pentru tastele apsate i eliberate fr tasta Alt.
Programul poate s foloseasc sau s ignore aceste mesaje.
Sistemul de operare le ignor.
Variabila lParam
lParam - ase cmpuri: contorul de repetare, codul de
scanare OEM, indicatorul flag pentru taste extinse, codul de
context, starea anterioar a tastei i starea de tranziie

Contorul de repetare (CR) specific numrul de acionari de


taste reprezentat de un mesaj - rata de autorepetare a
tastelor depete posibilitile de prelucrare ale programului.
Alte cmpuri
Codul de scanare OEM
Codul de scanare OEM (OEM Scan Code) este codul
de scanare al tastaturii, generat de componentele
hardware. (este identic cu cel transmis n registrul
AH, n timpul ntreruperii apelului BIOS 16H.)
Indicatorul flag pentru taste extinse
Indicatorul flag pentru taste extinse (Extended Key
Flag) are valoarea 1 dac mesajul este generat de
una dintre tastele suplimentare de pe tastatura IBM
extins.
Alte cmpuri
Codul de context
Codul de context (Context Code) are valoarea 1 dac
este apsat tasta Alt.
Starea anterioar a tastei
Starea anterioar a tastei (Previous Key State) are
valoarea 0 dac tasta nu a fost anterior apsat, i
valoarea 1 dac tasta a fost apsat.
Starea de tranziie
Starea de tranziie (Transition State) are valoarea 0
dac tasta este apsat i valoarea 1 dac tasta este
eliberat.
Coduri virtuale de taste
wParam conine codul virtual care identific tasta apsat sau eliberat.
Codurile virtuale pe care le vei folosi cel mai des au nume definite n fiierele
antet din Windows.

Identificator Necesar Tastatur IBM


Zecimal Hexa WINDOWS.H
1 01 VK_LBUTTON
2 02 VK_RBUTTON
3 03 VK_CANCEL Ctrl-Break
4 04 VK_MBUTTON
8 08 VK_BACK Backspace
9 09 VK_TAB Tab
12 0C VK_CLEAR Tasta numeric 5 cu tasta
Num Lock inactiv
13 0D VK_RETURN Enter
16 10 VK_SHIFT Shift
17 11 VK_CONTROL Ctrl
18 12 VK_MENU Alt
Starea tastelor de modificare
lParam i wParam nu spun nimic programului despre
starea tastelor de modificare. Putei s obinei starea
oricrei taste virtuale folosind funcia GetKeyState.
(Shift, Alt i Ctrl) i (Caps Lock, Num Lock i Scroll
Lock). De exemplu:
GetKeyState (VK_SHIFT) ;
returneaz o valoare negativ dac tasta Shift este
apsat. Valoarea returnat de apelul:
GetKeyState (VK_CAPITAL) ;
are un 1 n bitul cel mai puin semnificativ dac tasta
Caps Lock este activ.
Dac avei nevoie de starea curent a unei taste, putei
s folosii funcia GetAsyncKeyState.
Utilizarea mesajelor de ac ionare a tastelor

n general, programele pentru Windows folosesc mesajele


WM_KEYDOWN pentru tastele care nu genereaz caractere.
De cele mai multe ori vei prelucra mesajele WM_KEYDOWN
numai pentru tastele de deplasare a cursorului. Atunci cnd
prelucrai mesajele trimise de tastele de deplasare putei s
verificai i starea tastelor Shift i Ctrl, folosind funcia
GetKeyState:
Una dintre cele mai bune metode de a v hotr cum s
folosii tastatura este s studiai modul de utilizare a
acesteia n programele Windows existente. Dac nu v place
cum este folosit, putei s facei ceva diferit. Dar nu uitai
c orice noutate nseamn creterea perioadei de care are
nevoie un utilizator pentru a se obinui cu programul
dumneavoastr.
MBUN T IREA PROGRAMULUI
SYSMETS
case WM_KEYDOWN :
iVscrollInc = iHscrollInc = 0 ;
switch (wParam)
{
case VK_HOME: // la fel ca WM_VSCROLL, SB_TOP
iVscrollInc = -iVscrollPos ;
break ;
case VK_END : // la fel ca WM_VSCROLL, SB_BOTTOM:
iVscrollInc = iVscrollMax - iVscrollPos ;
break ;
case VK_UP : // la fel ca WM_VSCROLL, SB_LINEUP :
iVscrollInc = -1 ;
break ;
case VK_DOWN : // la fel ca WM_VSCROLL, SB_LINEDOWN
iVscrollInc =1;
break ;
default :
break ;
}
if (iVscrollInc = max (-iVscrollPos, min(iVscrollInc, iVscrollMax-iVscrollPos)))
{
iVscrollPos += iVscrollInc ;
ScrollWindow (hwnd, 0, -cyChar * iVscrollInc, NULL, NULL);
SetScrollPos (hwnd, SB_VERT, iVscrollPos, TRUE);
UpdateWindow (hwnd) ;
}
if (iHscrollInc = max (-iHscrollPos,min(iHscrollInc, iHscrollMax - iHscrollPos)))
{
iHscrollPos += iHscrollInc;
ScrollWindow (hwnd, -cxChar*iHscrollInc, 0, NULL, NULL) ;
SetScrollPos (hwnd, SB_ HORZ, iHscrollPos, TRUE) ;
}
return 0 ;
Transmiterea mesajelor
Nu ar fi mai bine s transformm mesajele WM_KEYDOWN n mesaje echivalente WM_VSCROLL i
WM_HSCROLL i s facem cumva funcia WndProc s cread c a primit mesajele WM_VSCROLL i
WM_HSCROLL, poate chiar transmind procedurii de fereastr aceste mesaje contrafcute?
Windows v permite s facei acest lucru. Funcia necesar este SendMessage i primete aceiai
parametri ca i procedura de fereastr:
SendMessage (hwnd, message, wParam, lParam) ;
Atunci cnd apelai funcia SendMessage, Windows apeleaz procedura ferestrei identificat de
parametrul hwnd i i transmite cei patru parametri. Dup ce procedura de fereastr ncheie
prelucrarea mesajului, Windows reia execuia de la urmtoarea linie dup apelul funciei
SendMessage. Procedura de fereastr creia i trimitei mesajul poate fi aceeai procedur de
fereastr, o alt procedur de fereastr din acelai program sau chiar o procedur de fereastr
dintr-o alt aplicaie.
Iat cum putem folosi funcia SendMessage pentru prelucrarea mesajelor WM_KEYDOWN n programul
SYSMETS:
case WM_KEYDOWN :
switch (wParam)
case VK_HOME :
SendMessage (hwnd, WM_VSCROLL, SB_TOP, 0L);
break;
case VK_END:
SendMessage (hwnd, WM_VSCROLL, SB_BOTTOM, 0L);
break ;

case VK_PRIOR :
SendMessage (hwnd, WM_VSCROLL, SB_PAGEUP, 0L);
break ;
[alte linii de program]
MESAJE CARACTER
Am discutat mai devreme despre ideea transformrii mesajelor generate de
acionarea tastelor n mesaje caracter innd cont de starea tastelor de
modificare i v-am avertizat c acest lucru nu este suficient: trebuie s inei
seama i de configuraia diferit a tastaturii de la o ar la alta. Din acest
motiv, nu trebuie s ncercai s transformai dumneavoastr mesajele
generate de acionarea tastelor n mesaje caracter. Windows o poate face n
locul dumneavoastr. Ai mai vzut aceast secven de cod:
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
Funcia GetMessage preia urmtorul mesaj din coada de ateptare i completeaz
cmpurile structurii msg. Funcia DispatchMessage transmite mesajul
procedurii de fereastr corespunztoare. ntre cele dou funcii este apelat
funcia TranslateMessage, care transform mesajele generate de acionarea
tastelor n mesaje caracter. Dac mesajul este WM_KEYDOWN sau
WM_SYSKEYDOWN i dac tasta apsat, n funcie de starea tastelor de
modificare, genereaz un caracter, atunci funcia TranslateMessage insereaz
un mesaj caracter n coada de ateptare. Acesta va fi urmtorul mesaj pe care
l va prelua funcia GetMessage dup mesajul generat de acionarea tastei.
Exist patru mesaje caracter:
MESAJE CARACTER
Caractere Caractere moarte"
Caractere non-sistem WM_CHAR WM_DEADCHAR
Caractere sistem WM_SYSCHAR WM_SYSDEADCHAR

Mesajele WM_CHAR i WM_DEADCHAR sunt obinute din mesaje WM_KEYDOWN. Mesajele


WM_SYSCHAR i WM_SYSDEADCHAR sunt obinute din mesaje WM_SYSKEYDOWN. n
majoritatea cazurilor programul poate s ignore toate celelalte mesaje n afar de WM_CHAR.
Parametrul lParam transmis procedurii de fereastr are acelai coninut ca i parametrul
lParam al mesajului generat de acionarea tastei din care a fost obinut mesajul caracter.
Parametrul wParam conine codul ASCII al caracterului. Mesajele caracter sunt transmise
procedurii de fereastr ntre mesajele generate de acionarea tastelor. De exemplu, dac tasta
Caps Lock nu este activ i apsai i eliberai tasta A, procedura de fereastr primete
urmtoarele trei mesaje

Mesaj Tast sau cod


WM_KEYDOWN Tasta virtual A
WM_CHAR Codul ASCII al caracterului a
WM_KEYUP Tasta virtual A
Dac introducei un caracter A apsnd tasta Shift, apoi tasta A,
elibernd tasta A i apoi elibernd tasta Shift, procedura de fereastr
primete cinci mesaje

Mesaj Tast sau cod


WM_KEYDOWN Tasta virtual VK_SHIFT
WM_KEYDOWN Tasta virtual A
WM_CHAR WM_KEYUP Codul ASCII al caracterului a
WM_KEYUP Tasta virtual A
Tasta virtual VK_SHIFT

Tasta Shift nu genereaz un mesaj caracter. Dac inei tasta A apsat pn


cnd intr n aciune autorepetarea, vei primi un mesaj caracter pentru
fiecare caracter WM_KEYDOWN
Mesaj Tast sau cod
WM_KEYDOWN Tasta virtual A
WM_CHAR Codul ASCII al caracterului a
WM_KEYDOWN Tasta virtual A
WM_CHAR Codul ASCII al caracterului a
WM_KEYDOWN Tasta virtual A
WM_CHAR Codul ASCII al caracterului a
WM_KEYDOWN Tasta virtual A
WM_CHAR Codul ASCII al caracterului a
WM_KEYUP Tasta virtual A
Examinarea mesagelor de la tastatur
CURSORUL DE EDITARE (CARET)
Atunci cnd introducei text ntr-un program, poziia n care va aprea urmtorul
caracter este indicat de o liniu de subliniere sau de un mic dreptunghi, n
Windows pentru acest semn se folosete termenul cursor de editare".
Funcii pentru cursorul de editare
Exist cinci funcii principale pentru cursorul de editare:
CreateCaret - creeaz un cursor de editare asociat unei ferestre.
SetCaretPos - stabilete poziia cursorului de editare n fereastr.
ShowCaret - afieaz cursorul de editare.
HideCaret - mascheaz cursorul de editare.
DestroyCaret - distruge cursorul de editare creat.
Mai exist i alte funcii pentru obinerea poziiei cursorului de editare (GetCaretPos)
i pentru stabilirea i obinerea intervalelor de licrire a acestuia
(SetCaretBlinkTime i GetCaretBlinkTime).
Cursorul de editare este, de obicei, o linie ori un bloc orizontal de dimensiunea unui
caracter, sau o linie vertical. Linia vertical este recomandat n cazul folosirii
unui font proportional, cum ar fi fontul sistem prestabilit din Windows. Deoarece
caracterele din fonturile proporionale nu au aceeai lime, linia sau blocul
orizontal nu poate avea limea exact a unui caracter.
Cursorul de editare nu poate fi creat pur i simplu n timpul prelucrrii mesajului
WM_CREATE i nici distrus n timpul prelucrrii mesajului WM_DESTROY. El este
ceea ce se numete o resurs de sistem". Aceasta nseamn c n sistem exist
un singur cursor de editare. De fapt, atunci cnd un program trebuie s afieze
un cursor de editare n fereastra proprie, el mprumut" acest semn de la
sistem.
Cursorul de editare
Afiarea unui cursor de editare ntr-o fereastr are sens numai dac fereastra respectiv
deine cursorul de intrare (input focus). Cursorul de editare indic utilizatorului faptul
c poate introduce text n program. La un moment dat, o singur fereastr poate
deine cursorul de intrare.
Un program poate determina dac deine cursorul de intrare prin prelucrarea mesajelor
WM_SETFOCUS i WM_KILLFOCUS. O procedur de fereastr recepioneaz un mesaj
WM_SETFOCUS atunci cnd primete cursorul de intrare i un mesaj WM_KILLFOCUS
atunci cnd pierde cursorul de intrare. Aceste mesaje sunt transmise n pereche. O
procedur de fereastr primete ntotdeauna un mesaj WM_SETFOCUS nainte de a
primi un mesaj WM_KILLFOCUS i ntotdeauna va primi un numr egal de mesaje
WM_SETFOCUS i WM_KILLFOCUS pan la distrugerea ferestrei.
Principala regul de folosire a cursorului de editare este simpl. O procedur de fereastr
apeleaz funcia CreateCaret n timpul prelucrrii mesajului WM_SETFOCUS i funcia
DestroyCaret n timpul prelucrrii mesajului WM_KILLFOCUS.
Exist i alte cteva reguli: la creare, cursorul de editare nu este afiat. Dup apelarea
funciei CreateCaret, programul trebuie s apeleze funcia ShowCaret pentru a face
vizibil cursorul de editare. n plus, procedura de fereastr trebuie s-l mascheze,
apelnd funcia HideCaret, ori de cte ori deseneaz ceva pe ecran n timpul prelucrrii
unui alt mesaj dect WM_PAINT. Dup terminarea operaiei de desenare, programul
apeleaz funcia ShowCaret ca s afieze din nou cursorul de editare.
Efectul funciei HideCaret este aditiv: dac apelai funcia HideCaret de mai multe ori fr
s apelai funcia ShowCaret, atunci cnd dorii ca acest cursor de editare s devin din
nou vizibil, trebuie s apelai funcia ShowCaret de tot attea ori de cate ori ai apelat
i funcia HideCaret.
Programul TYPER
Solu ia Unicode
Dezvoltatorii de programe implicai n crearea unor aplicaii pentru piaa
internaional au fost nevoii s inventeze diferite soluii pentru
rezolvarea deficienelor codului ASCII, cum ar fi paginile de coduri sau
seturile de caractere pe doi octei. Este nevoie de o soluie mai bun,
i aceasta este Unicode.
Unicode este un standard de codificare a caracterelor, care folosete un
cod uniform pe 16 bii pentru fiecare caracter. Acest cod permite
reprezentarea tuturor caracterelor, din toate limbajele scrise, care pot
fi folosite n comunicaiile prin calculator, inclusiv simbolurile
chinezeti, japoneze i coreene. Unicode a fost dezvoltat de un
consoriu de companii din industria calculatoarelor (inclusiv cele mai
mari dintre acestea).

Evident, adaptarea programelor (i a modului de gndire al


programatorilor) la ideea folosirii codurilor pe 16 bii este o sarcin
laborioas, dar merit dac n acest fel vom putea afia pe ecran i
vom putea tipri la imprimant texte n toate limbajele scrise
existente.