Primii pasi in programarea Windows sau cum scriu un program de log
Bernardt Huth YO2CMI
Articolul prezinta in linii mari structura unui program sub Windows API ( application programming interface ) precum si facilitatile mai simple puse la dispozitia programatorului de catre sistemul de operare.
Programul este scris in limbajul C++.
Pentru simplificare am incercat sa folosesc cat mai putin pointeri ( acces direct la memorie ) si sa evit teme mai complexe din C++ ( clase, iteratori, MDI e.t.c. ).
Pentru editare, compilare s.a.m.d . folosesc programul Code::Blocks, care la randul sau apeleaza la Microsoft Visual C++.
Cel mai bine vom putea intelege cum este realizat programul daca printam listingul ( .cpp ) si acest text, respectiv pornim programul de log (.exe ).
Formatul .cpp poate fi redat si de un editor de text obisnuit.
Listingul programului contine multe comentarii pe baza carora se poate urmari structura lui.
Un comentariu in C++ arata in felul urmator:
// comentariu
Un program sub Windows consta de obicei din trei parti:
- Initializarea variabilelor, a constantelor, declararea functiilor, respectiv al structurilor
- Apelarea functiei WinMain ( inceputul programului )
Deschiderea ferestrei ( cu sau fara meniu ) prin apelarea functiei CreateWindow
Daca dorim o fereastra fara meniu inlocuim in functia CreateWindow parametrul hMenu cu NULL.
Bucla principala ( de mesaje ), care este executata pana la primirea comenzii de iesire din program WM_QUIT
- Functia fereastra ( WndProc )
Toate operatiile pe care le executam in fereastra, inclusiv deplasarea si redimensionarea ferestrei constituie evenimente pe care sistemul Windows le transforma in mesaje. Acestea sunt preluate de programul nostru. In functie de mesajul primit se executa diferite parti din program.
Un program de log simplu este construit din urmatoarele parti:
- O baza de date in care memoram datele qso-urilor ( structura de date QSO )
- O secventa de program care deseneaza fereastra ( WM_CREATE, WM_PAINT )
- O secventa de program care analizeaza comenzile utilizatorului si in functie de aceasta seteaza anumite variabile sau executa anumite functii ( WM_COMMAND, GetAsyncKeyState )
- O parte de program care listeaza log-ul ( ListDB )
- O parte de program care salveaza / incarca datele de pe harddisk ( meniu - SAVE / OPEN )
- O subrutina de cautare indicativ
O structura de date este foarte folositoare in cazul in care avem mai multe date care sunt legate unele de altele cum este in cazul unui program de log. Pentru un QSO trebuie sa memoram data, ora, indicativul, banda, modul de lucru, raportul RST si eventual un comentariu.
Toate aceste date le legam impreuna declarand structura QSO.
In acest caz daca vrem sa apelam o anumita componenta adresarea ei va arata in felul urmator:
QSO[iNr].szCall
unde iNr este numarul QSO-ului, szCall variabila in care e memorat indicativul.
Apelarea la functii este folositoare spre exemplu in cazul in care avem in program secvente (mai multe linii de program) care se repeta.
In cazul programului de log avem doua asemenea functii:
Prima este RestoreDB. Aceasta functie scrie datele din variabilele folosite pentru stocarea temporara a datelor QSO-ului in structura QSO si incrementeaza variabila iNr ( se trece la urmatorul QSO ).
A doua functie ListDB listeaza in partea stanga a ferestrei ultimele 10 QSO-uri.
Pentru a construi grafic o fereastra, sistemul Windows API pune la dispozitia programatorului foarte multe facilitati:
- Butoane
Acestea sunt de mai multe tipuri si sunt folosite in programul de log pentru
alegerea benzilor prin butonul de optiune ( AUTORADIOBUTTON ),
alegerea modului de lucru prin casuta de optiune (AUTOCHECKBOX), respectiv butonul de comanda "LOG IT ?" ( PUSHBUTTON )
Butonul de tip "GROUPBOX" nu foloseste la altceva decat la incadrarea mai multor componente sub acelasi titlu.
Spre ex. BAND ( butoanele 160m - 70cm )
- Zone de editare
In program se folosesc pentru introducerea indicativului respectiv al unui comentariu.
Info. Aceste ferestre nu reactioneaza la tasta TAB. Exista mai multe solutii pentru a rezolva aceasta problema:
a. Folosim functia GetAsyncKeyState() cu care putem afla in timp real starea unei anumite taste. Aceasta facilitate am introdus-o in bucla principala a programului, unde la intervale regulate se testeaza atat tasta TAB cat si tasta RETURN.
Partea de timing din bucla principala foloseste pentru accesarea periodica a tastelor.
b. Prin definirea unei subclase fereastra
folosind functia CALLBACK.
- Clasa Static
Aici pot fi listate texte, grafice sau se foloseste pentru a eticheta un alt control.
Deasemenea poate fi folosita pentru a desena un dreptunghi.
Spre ex. eticheta CALLSIGN
- Zone de listare "listbox"
Aici utilizatorul poate alege una sau mai multe valori dintr-o lista data
Felul cum se introduc diferitele date - vezi listingul .cpp ( CAT Speed )
- Bare de defilare "scrollbar"
Sunt utile cand vrem sa schimbam continuu valoarea unei variabile
Ex. Viteza CW ( WPM ), volum etc
Aceste ferestre pot fi desenate vertical sau orizontal
Pentru a scrie un text pe ecran se foloseste deobicei functia TextOut.
Alta modalitate sunt ferestrele tip Edit sau Static
Formatul pentru TextOut in C++ este:
TextOut (hdc, x, y, buffer, marime buffer)
Exemplu: TextOut ( hdc, 100, 200, "exemplu", 7 )
In cazul in care dorim sa scriem pe ecran folosind un anumit format atunci functia se complica putin:
TextOut ( hdc, x, y, buffer, wsprintf ( buffer, TEXT("%3d %2d"), variabila1, variabila 2))
Functia wsprintf scrie in buffer cum trebuie formatate datele
spre ex. 2d - 2 digiti, 3s - 3 caractere, X -hexa
Inainte de a folosi functia TextOut trebuie aflat contextul dispozitiv ( device context ) prin apelarea functiei GetDC. Functia returneaza parametrul hdc.
Contextul dispozitiv este o structura asociata unui dispozitiv de afisare (display e.t.c. ).
Pentru a alege culoarea textului respectiv a fundalului putem utiliza functiile
SetTextColor respectiv SetBkColor.
In functie de ce actiuni intreprindem in fereasta programului ( mouse, tastatura ) sistemul ne va transmite anumite mesaje.
La actionarea unui buton sistemul Windows va genera mesajul WM_COMMAND.
Pentru a identifica care buton a fost actionat ne sta la dispozitie ID-ul butonului (identificatorul se alege la crearea butonului) care se compara cu variabila wParam.
In functie de ce buton a fost actionat vom intreprinde actiunile corespunzatoare.
Spre ex. daca sa activat butonul 80M atunci vom da variabilei iB valoarea 80.
La butonul tip AUTOCHECKBOX vom folosi functia
SendMessage (denumire_buton, BM_GETSTATE, 0, 0L)
care ne va returna starea butonului.
La fereastra tip LISTBOX se foloseste functia
SendMessage ( denumire_fereastra, LB_GETCURSEL, 0, 0L)
care ne va returna pozitia selectata.
La actionarea unei ferestre tip scrollbar sistemul va trimite mesajul WM_VSCROLL
VSCROLL in cazul cand cursorul este desenat vertical.
In functie de valoarea lui ID ( variabila wParam ) vom sti ce comanda sa dat ( spre ex. scroll in jos -> 1 ).
Mesajul WM_CREATE:
Functia CreateWindow este apelata la inceputul programului. Aceasta functie genereaza mesajul WM_CREATE cu care apeleaza direct functia fereastra.
Deci la deschiderea ferestrei vor fi executate si liniile de program aflate in functia fereastra la WM_CREATE.
Mesajul WM_PAINT este generat de functia UpdateWindow. Acest mesaj se va genera si cand se redimensioneaza fereastra.
Mesajul WM_SIZE - acest mesaj este generat la redimensionarea ferestrei
Mesajul SET_FOCUS
Pentru a activa o anumita fereastra ( spre ex. cea de introducere indicativ ), sistemul pune la dispozitie comanda:
SetFocus ( denumire_fereastra )
La alegerea ID-urilor trebuie avut grija ca unui ID sa-i fie atribuit un numar unic.
Salvarea / incarcarea de pe harddisk se face utilizand functii specifice din setul <iostream> si se face in format binar. Fisierul se salveaza in acelasi director cu programul.
Lungimea programului poate fi redusa prin preluarea tuturor datelor de creare a butoanelor intr-o structura si folosind ulterior o bucla for() pentru crearea lor, dar am ales aceasta cale pentru intelegerea mai usoara a programului.
Modul de lucru, banda, raportul RST se memoreaza temporar in mai multe variabile care se definesc la inceputul programului ( szM, iB, iR). Raportul RST nu poate fi schimbat de utilizator.
Datele pentru un QSO se memoreaza definitiv abia dupa ce apasam butonul "LOG IT ?" sau actionam tasta ENTER.
In fereastra CALLSIGN se verifica numarul de caractere introduse. Daca indicativul introdus are mai putin de 3 caractere QSO-ul nu se memoreaza.
Pentru a afisa ce qso-uri sau efectuat cu un anumit indicativ se introduce indicativul in fereastra CALLSIGN si se apasa butonul de comanda SEARCH. Rezultatele vor fi afisate in partea de jos a ferestrei.
Cu comanda CLEAR se sterg aceste rezultate.
Facilitatile CAT, WPM nu sunt implementate. Sunt date doar ca exemple pentru tipurile respective de ferestre.
Pentru programatorii care vor sa acceseze porturile seriale, Windows pune la dispozitie mai multe functii, portul COM1 fiind spre ex. deschis prin comanda
hCom = CreateFile ( TEXT("COM1"),...)
Setarea parametrilor pentru comunicatia seriala se face cu comanda
SetCommState (hCom, lista cu parametrii - exista o structura predefinita: DCB )
Programul este limitat la 1000 de qso-uri, dar programatorul poate schimba usor limita maxima prin schimbarea marimii constantei MaxQso.
Pentru cei care vor sa aprofundeze programarea sub Windows le recomand bibliografia existenta precum si internetul unde se gasesc multe pagini cu tutoriale despre Windows si limbajul de programare C++.
Spre ex.:
http://msdn2.microsoft.com/en-us/library/aa383723.aspx
Descarcati listingul .cpp si fisierul .exe.
Folosind termeni in limba romana,
descarcati listingul .cpp si fisierul .exe.
- Bernardt Huth YO2CMI
-
Articol aparut la
11-10-2007
22081
Inapoi la inceputul articolului
|