ďťż

Blog literacki, portal erotyczny - seks i humor nie z tej ziemi


LEKCJA 39: KORZYSTAMY ZE STANDARDOWYCH ZASOBÓW Windows.
________________________________________________________________
W trakcie tej lekcji dowiesz się, jak korzystać z zasobów
Windows bez potrzeby wnikania w wiele szczególów technicznych
interfejsu aplikacji - Windows API.
________________________________________________________________

Ponieważ nasze programy mogą korzystać ze standardowych zasobów
Windows, na początku będziemy posługiwać się okienkami
standardowymi. Począwszy od aplikacji WIN3.EXE "rozszerzymy
ofertę" do dwu podstawowych typów:

* Standardowe główne okno programu (Default main window).
To takie właśnie okno, jakie dostały nasze pierwsze aplikacje
WIN1.EXE.
* Okienkiem dialogowym (Dialog box),
a dokładniej najprostszym rodzajem okienek dialogowych - tzw.
okienkami komunikatów - Message Box.

Zastosowanie okienka dialogowego pozwoli nam na wprowadzenie do
akcji klawiszy (buttons).

________________________________________________________________

UWAGA:
Niestety nie wszystkie tradycyjne funkcje typu printf(),
scanf(), gets() itp. zostały zaimplementowane dla Windows!
Pisząc własne programy możesz przekonać się o tym dzięki opisowi

funkcji w Help. Funkcję należy odszukać w Help | Index. Oprócz
przykładu zastosowania znajdziesz tam tabelkę typu:

DOS Unix Windows ANSI C C++ Only
cscanf Yes
fscanf Yes Yes Yes Yes
scanf Yes Yes Yes
sscanf Yes Yes Yes Yes

[Yes] oznacza "zaimplementowana". Dlatego właśnie w dalszych
programach przykładowych dla wersji 3.0 należy np. stosować np.
makro getchar() zamiast tradycyjnego getch() zaimplementowane
dla Windows już w wersji BC++ 3.0.
________________________________________________________________


Dla przykładu spróbujmy skompilować i uruchomić w środowisku
Windows jeden z wcześniejszych programów - tabliczkę mnożenia.
Zwróć uwagę na dołączony dodatkowy plik WINDOWS.H i nowy typ
wskaźnika. Zamiast zwykłego

char *p ...
LPSTR p ...

LPSTR - to Long Pointer to STRing - daleki wskaźnik do łańcucha
tekstowego. Jest to jeden z "ulubionych" typów Windows.

/* WIN2.CPP: */
/* - Tablica dwuwymiarowa
- Wskazniki do elementów tablicy */

#include
#include
#include

int T[10][10], *pT, i, j, k;
char spacja = ' ';

LPSTR p1 = " TABLICZKA MNOZENIA (ineksy)\n";
LPSTR p2 = " Inicjujemy i INKREMENTUJEMY wskaznik:\n";
LPSTR p3 = "... nacisnij cokolwiek (koniec)...";

void main()
{
printf(p1);
for (i = 0; i < 10; i++)
{
for (j = 0; j < 10; j++)
{ T[i][j] = (i + 1)*(j + 1);
if (T[i][j] < 10) cout << T[i][j] << spacja << spacja;
else
cout << T[i][j] << spacja;
}
cout << '\n';
}
printf(p2);
pT = &T[0][0];
for (k = 0; k < 10*10; k++)
{
if (*(pT+k) < 10) cout << *(pT + k) << spacja << spacja;
else
cout << *(pT + k) << spacja;
if ((k + 1)%10 == 0) cout << '\n';
}
printf(p3);
getchar();
}

Wybraliśmy dla aplikacji standardowe główne okno (Main Window),
ponieważ istnieje potrzeba pionowego przewijania okna w celu
przejrzenia pełnego wydruku obu tablic.

[???] Dlaczego ten tekst jest nierówny???
________________________________________________________________
Niestety, znaki w trybie graficznym Windows nie mają stałej
szerokości (jak było to w trybie tekstowym DOS). Niektóre
aplikacje przeniesione ze środowiska DOS będą sprawiać kłopoty.
________________________________________________________________

APLIKACJE DWUPOZIOMOWE.

Zastosujemy teraz najprostszy typ okienka dialogowego - okienko
kamunikatów (Message Box), nasze następne aplikacje mogą być już

nie jedno- a dwupoziomowe. Typowe postępowanie okienkowych
aplikacji bywa takie:

* program wyświetla w głównym oknie to, co ma do powiedzenia;
* aby zadawać pytania stosuje okienka dialogowe, bądź okienka
komunikatów;
* funkcja okienkowa (u nas MessageBox()) zwraca do programu
decyzję użytkownika;
* program główny analizuje odpowiedź i podejmuje w głównym oknie

stosowne działania.

Prześledźmy ewolucję powstającej w taki sposób aplikacji.

STADIUM 1. Tekst w głównym oknie.

Zaczniemy tworzenie naszej aplikacji tak:

/* WINR1.CPP: */
/* Stadium 1: Dwa okienka w jednym programie */

# include
# include

char *p1 = "Teraz dziala \n funkcja \n MessageBox()";
char *p2 = "START";
int wynik;

void main()
{
printf(" Start: Piszemy w glownym oknie \n");
printf(" ...nacisnij cosik...");
getchar();
MessageBox(0, p1, p2, 0);
printf("\n\n\n Hello World dla WINDOWS!");
printf("\n\t...dowolny klawisz... ");
getchar();
}

Moglibyśmy zrezygnować z metod typowych dla aplikacji DOSowskich

i zatrzymania (i zapytania) makrem getchar() (odpowiednik
getch() dla Windows). To działanie możemy z powodzeniem
powierzyć funkcji okienkowej MessageBox(). Funkcja MessageBox()
pobiera cztery parametry:

int Message Box(hwndParent, lpszText, lpszTitle, Style)

HWND hwndParent - identyfikator macieżystego okna (głównego okna

aplikacji). Ponieważ nie wiemy póki co pod jakim numerem
(identyfikatorem) Windows zarejestrują naszą aplikację -
wpisujemy 0
LPCSTR lpszText - daleki wskaźnik do łańcucha tekstowego
wewnątrz okienka.
LPCSTR lpszTitle - daleki wskażnik do łańcucha tekstowego -
tytułu okienka komunikatu.
UINT Style - UINT = unsigned int; numer określający zawartość
okienka.
int Return Value - identyfikator klawisza, który wybrał
użytkownik w okienku komunikatu.

[!!!] UWAGA
________________________________________________________________
Deklaracje wskaźników do tekstów powinny wyglądać tak:
LPCSTR p1 = "Napis1", p2 = "Tekst2";
ale C++ może samodzielnie dokonać forsowania typów i zamienić
typ char* na typ LPCSTR (lub LPSTR).
________________________________________________________________

/* WINR2.CPP: */
/* Stadium 2: Dwa okienka ze zmienną zawarością */

# include
# include

char *p2, *p1 = "Dopisywanie:";
char napisy[4][20] = { "Borland ", "C++ ", "dla ", "Windows" };

void main()
{
printf("\n\n\n Hello World dla WINDOWS!");
printf("\n AUTOR: ...................");

for( int i = 0; i < 4; i++)
{
p2 = &napisy[i][0];
MessageBox(0, p2, p1, MB_OK);
printf("\n %s", napisy[i]);
}
MessageBox(0, "I to juz \n wszystko...", "KONIEC", MB_OK);
}

W tym stadium stosujemy:

- główne okno aplikacji
- dwa okienka komunikatów (Dopisywanie i KONIEC)
- jeden klawisz - [OK]

Łańcuchy tekstowe przeznaczone do pola tekstowego okienka
pobierane są z tablicy napisy[4][20] (cztery napisy po max. 20
znaków) przy pomocy wskaźnika p2. MB_OK to predefiniowana stała
(Message Box OK - key identifier - identyfikator klawisza [OK]
dla okienek komunikatów).

/* WINR3.CPP: */
/* Stadium 3: Dwa okienka sterują pętlą */

# include
# include

char *p2, *p1 = "Dopisywanie:";
char napisy[4][20] = { "Borland ", "C++ ", "dla ", "Windows" };

void main()
{
printf("\n\n\n Hello World dla WINDOWS!");
printf("\n AUTOR: ...................");

for( int i = 0; i < 4; i++)
{
p2 = &napisy[i][0];
if( MessageBox(0, p2, p1, MB_ICONSTOP | MB_OKCANCEL) == IDOK)
printf("\n %s", napisy[i]);
else
printf("\n ...?");
}
MessageBox(0, "I to juz \n wszystko...", "KONIEC", MB_OK);
}


W tym stadium stosujemy:

- główne okno aplikacji
- dwa okienka komunikatów (Dopisywanie i KONIEC)
- dwa klawisze - [OK] i [Anuluj] (OK/Cancel)
- jedną ikonę [STOP]

Zwróć uwagę, że tym razem sprawdzamy, który klawisz wybrał
użytkownik w okienku. Odbywa się to tak:

if( MessageBox(0, p2, p1, MB_ICONSTOP | MB_OKCANCEL) == IDOK)

IDOK jest predefiniowaną stałą - kodem klawisza [OK] (ang.
OK-key IDentifier - identyfikator klawisza OK). Identyfikatory
różnych zasobów Windows są liczbami całkowitymi. Jeśli jesteś
dociekliwy Czytelniku, możesz sprawdzić - jaki numer ma klawisz
[OK] rozbudowując tekst aplikacji np. tak:

int Numer;
...
Numer = MessageBox(0, p2, p1, MB_ICONSTOP | MB_OKCANCEL);
printf("\nKlawisz [OK] ma numer: %d", Numer);
if(Numer == IDOK) ...

Zwróć uwagę na sposób wykorzystania zasobów w funkcji
MessageBox(). Identyfikatory zasobów, które chcemy umieścić w
okienku są wpisywane jako ostatni czwarty argument funkcji i
mogą być sumowane przy pomocy znaku | (ang. ORing), np.:

MessageBox(0,..,.., MB_ICONSTOP | MB_OKCANCEL);

oznacza umieszczenie ikony STOP i klawiszy [OK] i [Anuluj]. Kod
zwracany przez funkcję może być wykorzystywany we wszelkich
konstrukcjach warunkowych (switch, case, for, while, if-else,
itp.).

/* WINR4.CPP: */
/* Stadium 4: Okienka sterują 2 pętlami, przybywa zasobów. */

# include
# include

char *p2, *p1 = "Dopisywanie:";
char *p3 = "I to by bylo na tyle...\n Konczymy ???";
char *p4 = "UWAGA: KONIEC ?";
char napisy[5][20] = { "Borland ", "C++ ", "dla ", "Microsoft",
"Windows" };

main()
{
printf("\n\n\n Grafoman dla WINDOWS!");
printf("\n AUTOR: (jak wyzej)");
puts("_____________________________\n");

do
{
for( int i = 0; i < 5; i++)
{
p2 = &napisy[i][0];
if( MessageBox(0, p2, p1, MB_ICONSTOP | MB_OKCANCEL) == IDOK)
printf("\n %s", napisy[i]);
else
printf("\n ...?");
}
} while
(MessageBox(0,p3,p4,MB_ICONQUESTION | MB_OKCANCEL)==IDCANCEL);

return 0;
}

W tym stadium stosujemy:

- główne okno aplikacji
- dwa okienka komunikatów (Dopisywanie i KONIEC)
- dwa klawisze - [OK] i [Anuluj] (OK/Cancel)
- dwie ikonki [STOP] i [PYTAJNIK]

Tekst jest przewijany w głównym oknie programu i po zakończeniu
roboczej części programu i przejściu w stan nieaktywny
(inactive) możesz przy pomocy paska przewijania pionowego
obejrzeć napisy - historię Twoich zmagań z programem. Zwróć
uwagę, że pojemność głównego okna jest ograniczona. Jeśli
napisów będzie zbyt dużo, tekst przewinięty poza okno może
ulegać obcięciu (ang clip on). Zwróć również uwagę na
naprzemienne przekazywanie aktywności (focus) pomiędzy oknami
aplikacji:

MainWindow <-----> MessageBox

Warto w tym momencie zwrócić uwagę na kilka typowych dla
okienkowych aplikacji mechanizmów.

* Jeśli naciśniemy klawisz na klawiaturze, bądź klawisz myszki,
obsługa takiego zdarzenia może następować na dwa sposoby.
Najpierw Windows pobierają kod klawisza i dokonują
"kolejkowania" (podobnie jak DOS-owski bufor klawiatury).
Następnie przekazują kod klawisza aplikacji do obsługi. Jeśli
aplikacja czeka na klawisz i potrafi obsłużyć takie zdarzenie
(np. funkcja MessageBox(), bądź makro getchar(), czy operator
cin >> w programie głównym), obsługa zdarzenia zostaje
zakończona. Jeśli aplikacja nie potrafi obsłużyć zdarzenia -
obsługa przekazywaba jest stadardowym funkcjom obsługi (Event
Handler) Windows.
* Kiedy na ekranie pojawia się okienko dialogowe (tu:
komunikatów) zostaje mu przekazany tzw. focus - czyli aktywność.

Naciśnięcie [Entera] spowoduje zadziałanie tego klawisza w
okienku, który właśnie ten focus otrzymał (tu zwykle pierwszego
z lewej).
* jeśli naciśniemy klawisz specjalny, którego obsługę w sposób
standardowy powinny załatwiać Windows - obsługa takiego
zdarzenia zostaje przekazana domyślnej funkcji Windows (ang.
Default Event Handler). Tak jest w przypadku klawiszy ze
strzałkami (przewijanie w oknie), [Tab], [Alt]+[F4], itp.

/* WINR5.CPP: */
/* Stadium 5: Zmiana wielkości i nazwy okienka. */

# include
# include
# include

char tytul[80] = "Dopisywanie: ";
char *p0, *p2;
char *p1 = "UWAGA: Ponawianie proby \n oznacza: WYDRUKUJE I
ZAPYTAM";
char *p3 = "I to by bylo na tyle...\n Konczymy ???";
char *p4 = "UWAGA: KONIEC ?";
char napisy[5][20] = { "Borland ", "C++ ", "dla ", "Microsoft",
"Windows" };

main()
{
cout << "\n\n\n Grafoman dla WINDOWS!";
cout << "\n AUTOR: (jak wyzej)";
cout << "\n_____________________________\n";

p0 = &tytul[0];
do
{
for( int i = 0; i < 5; i++)
{
p2 = &napisy[i][0];
strcat(p0, p2);
int decyzja = MessageBox(0, p1, p0, MB_ICONHAND |
MB_ABORTRETRYIGNORE);
if (decyzja == IDABORT) break;
else
if (decyzja == IDRETRY)
{
cout << "\n " << napisy[i];
i--;
}
else
if (decyzja == IDIGNORE)
{
cout << "\n ...?";
continue;
}
}
} while
(MessageBox(0, p3, p4, MB_ICONQUESTION | MB_OKCANCEL) ==
IDCANCEL);
return 0;
}

W Stadium 5 zmienia się (rośnie) nagłówek okienka komunikatów.

UWAGA: Po wyjściu za ekran nastąpi załamanie programu. Program
nie zawiera handlera obsługującego przekroczenia
dopuszczalnej długości.

Rysunek poniżej przedstawia różne stadia działania opisanych
powyżej aplikacji.

Jeśli postanowisz napisać praktyczną aplikację dla Windows, jest

to zwykle program znacznie dłuższy, w którym trzeba przemyśleć
sposób organizacji pętli, wyrażeń warunkowych i sposoby
wykorzystania zasobów.

[!!!]UWAGA
________________________________________________________________
Okienka mogą być "modalne" i "nie-modlane". Okienko "modalne" to

takie okienko, które do momentu jego zamknięcia uniemożliwia
użytkownikowi działania w innych oknach (tej samej aplikacji,
bądź innych aplikacji) znajdujących się na ekranie. W ramach
parametru Styl możesz stosować predefiniowane stałe
MB_APPMODAL
MB_TASKMODAL
itp.
określające stopień "modalności" okienka (na poziomie zadania -
TASK, aplikacji - APP, itp.).
________________________________________________________________
  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • qualintaka.pev.pl
  •