LEKCJA 38
O C++, Windows i małym Chińczyku.
czyli:
KTO POWIEDZIAŁ, ŻE PROGRAMOWANIE DLA WINDOWS JEST TRUDNE?!!!
Jak świat światem ludzie przekazują sobie sądy, opinie, poglądy... W ciągu naszej nowożytnej ery wymyślono już wiele opinii, które krążyły przez dziesięcio- i stulecia gwarantując jednym komfort psychiczny (- Ja przecież mam swoje zdanie na ten temat!), innym dając pozory wiedzy (- Tak, ja coś o tym wiem, słyszałem, że...). Żywotność takich ćwierćprawd, uproszczeń, uogólnień, czy wręcz kompletnie bzdurnych mitów była i jest zadziwiająca. Podejmę tu próbę obalenia funkcjonującego powszechnie przesądu, że
- Programowanie dla Windows jest trudne. (BZDURA!!!)
Aby nie zostać całkowicie posądzonym o herezję, przyznaję na wstępie dwa bezsporne fakty. Po pierwsze, wielu powszechnie szanowanych ludzi zrobiło wiele, by już pierwszymi przykładami (zwykle na co najmniej dwie strony) skutecznie odstraszyć adeptów programowania dla Windows. No bo jak tu nie stracić zapału, gdy program piszący tradycyjne "Hello World." w okienku ma 2 - 3 stronice i jeszcze zawiera kilkadziesiąt zupełnie nieznanych i niezrozumiałych słów (skrótów? szyfrów?). Po drugie, wszystko jest trudne, gdy brak odpowiednich narzędzi. Nawet odkręcenie małej śrubki bywa niezwykle trudne, gdy do dyspozycji mamy tylko młotek... Napisanie aplikacji okienkowej przy pomocy Turbo Pascal 6, Turbo C, Quick C, czy QBASIC rzeczywiście BYŁO nadwyraz trudne. I tu właśnie dochodzimy do sedna sprawy:
(!!!) Programowanie dla Windows BYŁO trudne (!!!)
UWAGA!
Pierwsza typowa aplikacja dla Windows napisana w BORLAND C++ 3/4 może wyglądać np. tak:
#include <iostream.h>
void main()
{
cout <<"Pierwsza Aplikacja dla Windows";
}
I już!
Niedowiarek zapyta: - I TAKIE COŚ CHODZI POD Windows???
TAK!.
W BORLAND C++ 3+ ... 4+ wystarczy dobrać parametry pracy kompilatora i zamiast aplikacji DOS-owskiej otrzymamy program wyposażony we własne okienko, paski przewijania w okienku, klawisze, menu, ikonkę, itp., itd.!
O MAŁYM CHIŃCZYKU, czyli - NAJLEPIEJ ZACZĄĆ OD POCZĄTKU...
Istnieje jedyny sprawdzony sposób rozwiązywania zagadnień takiego typu - tzw. METODA MAŁEGO CHIŃCZYKA. WSZYSCY DOSKONALE WIEDZĄ, że język chiński jest szalenie trudny. Dlatego też mimo ogromnego wysiłku prawie NIKOMU nie udaje się biegle nauczyć chińskiego - z jednym wyjątkiem - wyjątkiem małego Chińczyka. Dlaczego? To proste. Mały Chińczyk po prostu o tym nie wie! I dlatego już po kilku latach doskonale swobodnie włada tym bodaj najtrudniejszym językiem świata! Jeśli zatem komuś udało się przekonać Cię, szanowny Czytelniku, że programowanie dla Windows jest trudne, namawiam Cię na dokonanie pewnego eksperymentu intelektualnego. Spróbuj zapomnieć, że masz już na ten temat jakieś zdanie i wczuj się w rolę małego Chińczyka. Co roku udaje się to wielu milionom przyszłych ekspertów od wszystkich możliwych języków świata (C++ jest chyba znacznie łatwiejszy do chińskiego). BORLAND C++ aby dopomóc programiście w jego ciężkiej pracy tworzy (często automatycznie) wiele plików pomocniczych. Krótkie zestawienie plików pomocniczych zawiera tabela poniżej. Najważniejsze pliki pomocnicze w kompilatorach Borland/Turbo C++.
Najważniejsze pliki pomocnicze w kompilatorach Borland/Turbo C++ |
||
Rozszeżenie |
Przeznaczenie |
Gdzie / Uwagi |
.C .CPP |
Teksty źródłowe (ASCII) |
\EXAMPLES \SOURCE (przykłady) (kod żródłowy) |
.H .HPP .CAS |
Pliki nagłówkowe (ASCII) |
\Include |
.PRJ .DPR .IDE |
Projekty |
\EXAMPLES \SOURCE |
.TAH .TCH .TDH .TFH .HLP .HPJ .RTF |
Help |
|
.DSK .TC .CFG .DSW .BCW |
Konfiguracyjne |
|
.DEF .RC .RES .RH .ICO .BMP |
Zasoby i definicje |
|
.BGI .CHR .RTF |
Grafika DOS, fonty |
|
.MAK .NMK .GEN MAKEFILE |
Pliki instruktażowe dla MAKE.EXE |
|
.ASM .INC .ASI |
Do asemblacji (ASCII) |
|
.RSP |
Instruktażowy dla TLINK |
|
.LIB .DL |
Biblioteki |
|
.TOK |
Lista słów astrzeżonych (ASCII) |
(reserved words) |
.DRV |
Sterowniki (drivery) |
|
.OVL |
Nakładki (overlay) |
|
.SYM |
Plik ze skompilowanymi plikami nagłówkowymi. |
(Pre - compiled) |
Świadome i umiejętne wykorzystanie tych plików może znacznie ułatwić i przyspieszyć pracę. Po wprowadzeniu na rynek polskiej wersji Windows 3.1 okienka zaczęły coraz częściej pojawiać się w biurach i domach, i stanowią coraz częściej naturalne (właśnie tak, jak chiński dla Chińczyków) środowisko pracy dla polskich użytkowników PC. Nie pozostaje nam nic innego, jak po prostu zauważyć i uznać ten fakt. Po uruchomieniu Borland C++ (2 * klik myszką, lub rozkaz Uruchom z menu Plik) zobaczymy tradycyjny pulpit (desktop) zintegrowanego środowiska IDE - podobny do Turbo Pascala, z radycyjnym układem głównego menu i okien roboczych. Skoro mamy zająć się tworzeniem aplikacji dla Windows- zaczynamy od rozwinięcia menu Options i wybieramy z menu rozkaz Application... . Rozwinie się okienko dialogowe. Przy pomocy klawiszy możemy wybrać sposób generowania aplikacji - dla DOS, dla Windows lub tworzenie bibliotek statycznych .LIB, czy też dynamicznych .DLL. Wybieramy oczywiście wariant [Windows EXE].
[!!!]UWAGA!
Struktura podkatalogów i wewnętrzna organizacja pakietów 3.0, 3.1, 4 i 4.5 ZNACZNIE SIĘ RÓŻNI.
Skoro ustawiliśmy już poprawnie najważniejsze dla nas parametry konfiguracyjne - możemy przystąpić do uruchomienia pierwszej aplikacji dla Windows. PIERWSZA APLIKACJA "specjalnie dla Windows". Tryb postępowania z kompilatorem BORLAND C++ 3.0/3.1 będzie w tym przypadku dokładnie taki sam, jak np. z Turbo Pascalem. Wszystkich niezbędnych zmian w konfiguracji kompilatora już dokonaliśmy. Kompilator "wie" już, że chcemy uzyskać w efekcie aplikację dla Windows w postaci programu .EXE. Możemy zatem
* Wydać rozkaz File | New
Pojawi się nowe okienko robocze. Zwróć uwagę, że domyślne rozszerzenie jest .CPP, co powoduje domyślne zastosowanie kompilatora C++ (a nie kompilatora C - jak w przypadku plików z rozszerzeniem .C). Możesz to oczywiście zmienić, jeśli zechcesz,
posługując się menu Options | Compiler | C++ options... (Opcje |
Kompilator | Kompilator C albo C++). W tym okienku dialogowym
masz sekcję:
Use C++ Compiler: Zastosuj Kompilator C++
(zamiast kompilatora C)
(.) CPP extention - tylko dla rozszerzenia .CPP
( ) C++ always - zawsze
* Wybierz rozkaz Save as... z menu File Pojawi się okienko dialogowe "Save File As" (zapis pliku pod wybraną nazwą i w wybranym miejscu).
* Do okienka edycyjnego wpisz nazwę pliku i pełną ścieżkę dostępu - np. A:\WIN1.CPP lub C:\C-BELFER\WIN1.CPP
Zmieni się tytuł roboczego okna z NONAME00 na wybraną nazwę Możemy wpisać tekst pierwszego programu:
[P133.CPP]
#include <iostream.h>
void main()
{
cout << " Pierwsza Aplikacja " << " Dla MS Windows ";
}
Po wpisaniu tekstu dokonujemy kompilacji.
* Wybierz rozkaz Compile to OBJ z menu Compile.
* Wybierz rozkaz Link lub Make z menu Compile. W okienku komunikatów (Messages) powinien pojawić się w trakcie konsolidacji komunikat ostrzegawczy:
*Linker Warning: No module definition file specified: using defaults
Oznacza to: Konsolidator ostrzega, że brak specjalnego stowarzyszonego z plikiem .CPP tzw. pliku definicji sposobu wykorzystania zasobów Windows - .DEF. Program linkujący zastosuje wartości domyślne. Jeśli w IDE wersji kompilatora przeznaczonej dla środowiska DOS spróbujesz uruchomić program WIN1.EXE w tradycyjny sposób - rozkazem Run z menu Run - na ekranie pojawi się okienko z komunikatem o błędzie (Error message box):
Can't run a Windows EXE file
D:\WIN1.EXE
[ OK ]
czyli: "Nie mogę uruchomić pliku EXE dla Windows". Jak już napisałem wcześniej, kompilatory C++ w pakietach 3.0/3.1 mają swoje ulubione specjalności:
Borland C++ - jest zorientowany na współpracę z DOS
Turbo C++ - jest zorientowany na współpracę z Windows
w wersji 3.1:
BCW - dla Windows
BC - dla DOS
nie oznacza to jednak, że będą kłopoty z pracą naszego programu! Wyjdź z IDE BC/BCW. Z poziomu Menedżera Programów możesz uruchomić swój program rozkazem Plik | Uruchom. Do okienka musisz oczywiście wpisać poprawną ścieżkę do pliku WIN1.EXE (czyli katalog wyjściowy kompilatora Borland C++).
*** Wybierz z menu głównego Menedżera Programów (pasek w górnej części ekranu) rozkaz Plik. Rozwinie się menu Plik.
*** Wybierz z menu Plik rozkaz Uruchom. Pojawi się okienko dialogowe uruchamiania programów. Wpisz pełną ścieżkę dostępu do programu - np.: D:\KATALOG\WIN1.EXE i "kliknij" myszką na klawiszu [OK] w okienku. Na ekranie pojawi się okno naszej aplikacji. Okno jest wyposażone w:
- Pasek z tytułem (Caption) - np.: A:\WIN1.EXE ;
- Klawisz zamykania okna i rozwinięcia standardowego menu (tzw. menu systemowego Windows) - [-] ;
- Paski przewijania poziomego i pionowego;
- Klawisze MINIMIZE i MAXIMIZE (zmniejsz do ikonki | powiększ na cały ekran) w prawym górnym narożniku okna;
Program znajduje się w wersji .EXE na dyskietce dołączonej do książki. Możesz uruchomić go z poziomu Menedżera Plików (Windows File Manager), Menedżera Programów (Windows Program Manager) lub z DOS-owskiego wiersza rozkazów (DOS Command Line):
C\>WIN A:\WIN1.EXE[Enter]
Co może nasza pierwsza aplikacja?
- Typową dla Windows techniką drag and drop - pociągnij i upuść możesz przy pomocy myszki przesuwać okno naszej pierwszej aplikacji po ekranie ("ciągnąc" okno za pasek tytułowy).
- Ciągnąc ramki bądź narożniki możesz zmieniać wymiary okna w sposób dowolny.
- Posługując się paskami przewijania możesz przewijać tekst w oknie w pionie i w poziomie.
- Miżesz zredukować okno do ikonki.
- Możesz uruchomić naszą aplikację wielokrotnie i mieć na ekranie kilka okien programu WIN1.EXE.
- Nasza aplikacja wyposażona jest w menu systemowe. Możesz rozwinąć menu i wybrać z menu jeden z kilku rozkazów.
Jeśli nie pisałeś jeszcze programów dla Windows - możesz być trochę zaskoczony. Gdzie w naszym programie jest napisane np. - co powinno znaleść się w menu??? Odpowiedź jest prosta - nigdzie. Podobnie jak programy tworzone dla DOS korzystają w niejawny sposób z zasobów systemu - standardowych funkcji DOS, standardowych funkcji BIOS, przerywań, itp - tak programy tworzone dla Windows mogą w niejawny sposób korzystać z zasobów środowiska Windows - standardowego menu, standardowych okien, standardowych klawiszy, itp.. Takie zasoby udostępniane przez środowisko programom aplikacyjnym nazywają się interfejsem API (Application Program Interface). Poznałeś już API DOS'a - jego przerywania i funkcje. Interfejs Windows nazywa się "Windows API" i to z jego gotowych funkcji właśnie korzystamy.
Uruchom program wielokrotnie (min. 4 razy). Wykonaj 4 - 6 razy
czynności oznaczone powyżej trzema gwiazdkami *** . Ponieważ nie zażądaliśmy, by okno programu było zawsze "na wierzchu" (on top)
- po każdym kolejnym uruchomieniu (nie musisz nic robić - nastąpi to automatycznie - zadba o to Menedżer Windows) poprzednie okno programu zniknie. Jeśli po czwartym (piątym) uruchomieniu programu zredukujesz okno Menedżera Programów do ikony (np. [-] i "do ikony" z menu systemowego) - okaże się, że "pod spodem" stale widać kaskadę okien naszej aplikacji WIN1.EXE (patrz rys. poniżej). Na rysunkach poniżej przedstawiono kolejne stadia pracy z naszą PIERWSZĄ APLIKACJĄ. Aplikacja WIN1.EXE została wyposażona w ikonkę systemową (znane Ci okienko). Ikonka jest transparentna (półprzezroczysta) i możemy ją także metodą drag and drop przenieść w dowolne miejsce
- np. do roboczego okna naszej aplikacji. Zwróć uwagę także natowarzyszący nazwie programu napis "inactive" (nieaktywna). Chodzi o to, że program zrobił już wszystko, co miał do zrobienia i zakończył się. DOS dołożyłby standardowo funkcję zwolnienia pamięci i zakończył program. W Windows niestety okienko nie zamknie się samo w sposób standardowy. W Windows, jak wiesz, możemy mieć otwarte jednocześnie wiele okien programów a aktywne jest (tylko jedno) zawsze to okno, do którego przekażemy tzw. focus. Okno to można rozpoznać po ciemnym pasku tytułowym. Właśnie z przyjęcia takiego sposobu podziału zasobów Windows pomiędzy aplikacje wynika skutek praktyczny - okno nie zamknie się automatycznie po zakończeniu programu - lecz wyłącznie na wyrażne życzenie użytkownika. API Windows zawiera wiele gotowych funkcji (np. CloseWindow() - zamknij okno, DestroyWindow() - skasuj okno i in.), z których może skorzystać programista pisząc aplikację. Nie jesteśmy więc całkiem bezradni. Spróbuj skompilować w opisany wyżej sposób i uruchomić pierwszą aplikację w takiej wersji:
#include <stdio.h>
void main()
{
printf(" Pierwsza Aplikacja \n Dla MS Windows ");
}
Jak łatwo się przekonać, całkowicie klasyczny, w pełni nieobiektowy program WIN1.C będzie w Windows działać dokładnie tak samo. Nasze aplikacje nie muszą bynajmniej być całkowicie obiektowe, chociaż zastosowanie obiektowej techniki programowania pozwala zmusić nasz komputer do zdecydowanie wydajniejszego działania.
PODSUMUJMY:
* Jeśli korzystamy wyłącznie ze standardowych zasobów środowiska Windows, tworzenie aplikacji dla Windows nie musi być wcale trudniejsze od tworzenia aplikacji DOS'owskich.
* Czy aplikacja ma być przeznaczona dla DOS, czy dla Windows możemy zdecydować "w ostatniej chwili" ustawiając odpowiednio robocze parametry kompilatora C++:
Options | Applications... | DOS standard
albo
Options | Applications... | Windows EXE
* Aplikacje skompilowane do wersji DOS'owskiej możemy uruchamiać wewnątrz kompilatora DOS'owskiego rozkazem Run | Run.
* Aplikacje skompilowane (ściślej - skonsolidowane) do wersji okienkowej możemy uruchamiać wewnątrz Windows z poziomu Menedżera Plików bądź Menedżera Programów rozkazem Uruchom z menu Plik.
* Dodatkowe pliki nagłówkowe .H i biblioteki .LIB .DLL znajdują się w katalogach
\BORLANDC\INCLUDE
\BORLANDC\OWL\INCLUDE
\BORLANDC\LIB
\BORLANDC\OWL\LIB
Ścieżki dostępu do tych katalogów należy dodać do roboczych katalogów kompilatora w okienku Options | Directories...
* Aplikacje nie korzystające z funkcji Windows API nie muszą dołączać okienkowych plików nagłówkowych. Jeśli jednak zechcemy zastosować funkcje i dane (stałe, struktury, obiekty, itp.) wchodzące w skład:
- Windows API
- Windows Stock Objects - obiekty "ze składu Windows"
- biblioteki klas Object Windows Library
należy dołączyć odpowiedni plik nagłówkowy:
#include <windows.h>
#include <windowsx.h>
#include <owl.h>
TYPOWE BŁĘDY I KŁOPOTLIWE SYTUACJE:
Należy pamiętać o ustawieniu właściwych katalogów roboczych kompilatora Options | Directories...
Przy bardziej skomplikowanych aplikacjach może wystąpićpotrzeba dobrania innego (zwykle większego) modelu pamięci. Modelem domyślnym jest model Small. Inne parametry pracy kompilatora ustawia się podobnie za pomocą menu Options.
4