Prezentowane materiały są przeznaczone dla uczniów szkół ponadgimnazjalnych. Autor artykułu: mgr Jerzy Wałaszek, wersja1.0 |
©2011 mgr
Jerzy Wałaszek
|
Konsola jest znakowym trybem pracy programu i nie wykorzystuje systemu graficznego Windows. W edytorze zostanie utworzony plik projektu konsoli.
Zmienne mogą zawierać bezpośrednie dane. Wpisz do okna edytora poniższy program, skompiluj go i uruchom:
#include <iostream> using namespace std; //--------------------------------------------------------------------------- #pragma hdrstop //--------------------------------------------------------------------------- #pragma argsused int main(int argc, char* argv[]) { int a; a = 10; cout << a << endl; system("pause"); return 0; } //---------------------------------------------------------------------------
Program tworzy zmienną a, wpisuje do niej liczbę 10, a następnie wyświetla w oknie konsoli jej zawartość. Funkcja system() wykonuje polecenie pause. które czeka na naciśnięcie dowolnego klawisza. Bez niej okno konsoli zostałoby prawie natychmiast zamknięte po zakończeniu programu i nic byśmy nie zobaczyli.
Zmienne mogą również zawierać adresy pamięci, w których przechowywane są dane. Takie zmienne nazywamy wskaźnikami lub wskazaniami (ang. pointer). Wprowadź do edytora poniższy program:
#include <iostream> using namespace std; //--------------------------------------------------------------------------- #pragma hdrstop //--------------------------------------------------------------------------- #pragma argsused int main(int argc, char* argv[]) { int a, b, *p; a = 10; b = 99; p = &a; // w p jest adres zmiennej a cout << *p << endl; p = &b; // w p jest adres zmiennej b cout << *p << endl; system("pause"); return 0; } //---------------------------------------------------------------------------
W programie zmienna p jest wskaźnikiem, który przechowuje adresy danych. Wskaźnik tworzymy dodając przed jego nazwę znak *. Dostęp do przechowywanych przez wskaźnik danych następuje poprzez *p. W programie tworzymy dwie zmienne a, b oraz wskaźnik p. W zmiennych a i b umieszczamy dane. Następnie do p wprowadzamy adres zmiennej a. Od tego momentu odwołanie do *p jest równoważne z odwołaniem do a. Następnie zawartość p na adres zmiennej b. Odwołanie do *p oznacza odwołanie do b.
Do edytora wprowadź kolejny program:
#include <iostream> using namespace std; //--------------------------------------------------------------------------- #pragma hdrstop //--------------------------------------------------------------------------- #pragma argsused int main(int argc, char* argv[]) { int a, b, * p; p = &a; // w p jest adres zmiennej a *p = 10; // do a wprowadzamy 10 poprzez wskaźnik p p = &b; // w p jest adres zmiennej b *p = 99; // do b wprowadzamy 99 poprzez wskaźnik p cout << a << endl << b << endl; system("pause"); return 0; } //---------------------------------------------------------------------------
Tym razem wykorzystujemy wskaźnik do umieszczenia danych pod wskazywanym przez niego adresem.
Wskaźniki wykorzystujemy często do przedzielania pamięci w sposób dynamiczny. Wprowadź do edytora program:
#include <iostream> using namespace std; //--------------------------------------------------------------------------- #pragma hdrstop //--------------------------------------------------------------------------- #pragma argsused int main(int argc, char* argv[]) { int *a, *b; a = new int; // tworzymy daną int i jej adres umieszczamy w a b = new int; // tworzymy daną int i jej adres umieszczamy w b *a = 10; // do utworzonej danej wprowadzamy 10 *b = 99; // do utworzonej danej wprowadzamy 99 cout << *a << endl << *b << endl; delete a; // usuwamy daną z pamięci delete b; // usuwamy daną z pamięci system("pause"); return 0; } //---------------------------------------------------------------------------
Powyższy program tworzy dwa wskaźniki a i b. Następnie przydziela im pamięć na dane za pomocą operatora new. Składnia jest następująca:
Operator new tworzy w pamięci obszar o takim rozmiarze, aby można było w nim pomieścić daną danego typu. Po utworzeniu tego obszaru zwraca jego adres. Zwrócony adres instrukcja przypisania umieszcza we wskaźniku. Teraz poprzez *wskaźnik możemy się odwoływać do zawartości tego obszaru.
Zmienne w C++ mogą być złożone, tzn. mogą naraz przechowywać więcej niż jedną daną. Wpisz do edytora poniższy program:
#include <iostream> using namespace std; //--------------------------------------------------------------------------- #pragma hdrstop //--------------------------------------------------------------------------- #pragma argsused // definiujemy strukturę struct struktura { int a,b; // elementy składowe struktury }; int main(int argc, char* argv[]) { struktura s; // tworzymy zmienną strukturalną s.a = 10; // do pola a struktury s wprowadzamy 10 s.b = 99; // do pola b struktury s wprowadzamy 99 cout << s.a << endl << s.b << endl; system("pause"); return 0; } //---------------------------------------------------------------------------
W programie definiujemy typ strukturalny o nazwie struktura. Zmienna tego typu zawiera dwa pola danych typu int o nazwach a i b. Tworzymy zmienną s typu struktura. Dostęp do pól a i b uzyskujemy w zmiennej za pomocą operatora kropka.
Wskaźniki mogą również zawierać adresy struktur. Wpisz do edytora poniższy program:
#include <iostream> using namespace std; //--------------------------------------------------------------------------- #pragma hdrstop //--------------------------------------------------------------------------- #pragma argsused // definiujemy strukturę struct struktura { int a,b; // elementy składowe struktury }; int main(int argc, char* argv[]) { struktura * p; // tworzymy wskaźnik do struktury p = new struktura; // tworzymy dynamiczną strukturę p->a = 10; // do pola a struktury wprowadzamy 10 p->b = 99; // do pola b struktury wprowadzamy 99 cout << p->a << endl << p->b << endl; delete p; // usuwamy strukturę z pamięci system("pause"); return 0; } //---------------------------------------------------------------------------
W programie wskaźnik p wskazuje obiekty typu struktura - w C++ wskaźniki również posiadają typy. Strukturę tworzymy dynamicznie w pamięci i jej adres umieszczamy we wskaźniku p. Dostęp do pól a i b struktury następuje poprzez operator ->, a nie kropka!
Zapamiętaj:
komponent -> Canvas
Dla funkcji składowych okna głównego wystarczy samo Canvas - funkcje składowe, które są częścią klasy okna (w dużym uproszczeniu klasa jest "strukturą", która oprócz pól danych może zawierać własne funkcje składowe) posiadają bezpośredni dostęp do wszystkich pól tej klasy oraz jej funkcji składowych. Jeśli jednak chcesz się odwołać do Canvas okna spoza klasy (czyli z funkcji zewnętrznej, która nie jest funkcją składową klasy), to musisz zastosować składnię:
okno -> Canvas
A dla komponentów tego okna:
okno -> komponent -> Canvas
Jest to spowodowane tym, iż klasa jest obiektem dynamicznym, do którego uzyskujemy dostęp poprzez wskaźnik okna. Również wszystkie komponenty są tworzone dynamicznie w pamięci i dostęp do ich pól oraz funkcji składowych następuje poprzez wskaźniki, dlatego używamy operatorów ->.
Na potrzeby tego rozdziału stwórz projekt okienkowy. Następnie w oknie Object Inspector wybierz zakładkę Events i kliknij dwukrotnie myszką obok zdarzenia onPaint. Zdarzenie to powstaje, gdy okno musi przerysować swoją zawartość. W edytorze powstanie funkcja obsługi zdarzenia onPaint dla okna głównego aplikacji:
//--------------------------------------------------------------------------- void __fastcall TForm1::FormPaint(TObject *Sender) { } //---------------------------------------------------------------------------
Dostęp do poszczególnych punktów na powierzchni Canvas uzyskujemy poprzez własność Pixels, która jest jakby tablicą dwuwymiarową (patrz na wyjaśnienie na końcu podrozdziału). Elementy tej tablicy odnoszą się do pikseli na powierzchni graficznej. Element:
Canvas->Pixels[x][y]
odnosi się do piksela leżącego w wierszu y i w kolumnie x na powierzchni graficznej. Współrzędne (0,0) odnoszą się do lewego górnego narożnika powierzchni. Zwiększając x, przesuwamy się w kierunku prawej krawędzi. Zwiększając y, przesuwamy się w dół. Na początek wprowadź do edytora poniższy kod:
//--------------------------------------------------------------------------- void __fastcall TForm1::FormPaint(TObject *Sender) { for(int i = 0; i < 200; i++) Canvas->Pixels[i][i] = 0; } //---------------------------------------------------------------------------
Gdy uruchomisz program, otrzymasz ukośną linię biegnącą w prawo i w dół od górnego narożnika okna. Linia jest w kolorze czarnym, ponieważ w jej pikselach umieściliśmy wartość 0. Do określania koloru piksela możesz użyć gotowej stałej. Oto niektóre z nich:
Nazwa stałej | Kolor |
clBlack | czarny |
clBlue | niebieski |
clFuchsia | fiołkowy |
clGray | szary |
clMaroon | kasztanowy |
clOlive | oliwkowy |
clRed | czerwony |
Opis tych stałych znajdziesz w pliku pomocy dla środowiska Borland: wystarczy w edytorze wpisać jedną ze stałych koloru, np. clBlack, wskazać ją kursorem tekstowym i wcisnąć klawisz F1.
Wypróbuj te stałe w programie.
Drugim sposobem określania koloru jest podanie intensywności kolorów podstawowych R - czerwonego, G - zielonego i B - niebieskiego. Tutaj musimy potraktować kolor piksela jako daną binarną składającą się z trzech bajtów. Każdy bajt określa intensywność barwy podstawowej:
Bajt B | Bajt G | Bajt R |
Bajty te najlepiej przedstawiać w postaci szesnastkowej - każdy będzie się składał z dwóch cyfr od 00 (wartość najmniejsza) do ff (wartość największa):
0xff0000
- kolor niebieski0x00ff00
- kolor zielony0x0000ff
- kolor czerwony0x00ffff
- kolor żółty0xffffff
- kolor biały
Wypróbuj ten sposób w naszym programie.
Innym sposobem określania koloru jest wykorzystanie makra RGB(r,g,b), gdzie r - składowa czerwona, g - składowa zielona i b - składowa niebieska.
Zastąp w edytorze funkcję FormPaint() nową:
//--------------------------------------------------------------------------- void __fastcall TForm1::FormPaint(TObject *Sender) { for(int y = 0; y < 256; y++) for(int x = 0; x < 256; x++) Canvas->Pixels[x][y] = RGB(x,0,0); } //---------------------------------------------------------------------------
Otrzymasz kwadrat wypełniony gradientem:
Pobaw się, wpisując do programu różne wersje makra RGB():
RGB(0,x,0)
RGB(0,0,y)
RGB(0,x,y)
RGB(y,x,255-y)
Zastanów się, jak narysować wypełnienie całej powierzchni okna aplikacji.
Canvas -> MoveTo(x,y) |
- | ustawia początek linii w punkcie (x,y). Na powierzchni graficznej nic nie jest rysowane. |
Canvas -> LineTo(x,y) |
- | rysuje linię od ostatnio ustawionego punktu do (x,y), lecz punktu końcowego nie ustawia. Punkt (x,y) staje się punktem początkowym dla następnej linii rysowanej za pomocą tej funkcji. Umożliwia to tworzenie łamanych. |
Kolor rysowanych linii definiuje własność Canvas -> Pen -> Color
.
Kolor możemy określić w taki sam sposób jak dla pikseli. Standardowym
kolorem rysowania linii jest kolor czarny.
Wpisz do edytora poniższy kod dla funkcji FormPaint():
//--------------------------------------------------------------------------- void __fastcall TForm1::FormPaint(TObject *Sender) { for(int i = 0; i < 256; i++) { Canvas->Pen->Color = RGB(i,i,0); // kolor linii, w każdym obiegu inny Canvas->MoveTo(i,i); // punkt początkowy trójkąta nr 1 Canvas->LineTo(512-i,i); // dolny bok Canvas->LineTo(512-i,512-i); // prawy bok Canvas->LineTo(i,i); // przekątna } for(int i = 0; i < 256; i++) { Canvas->Pen->Color = RGB(i,0,i); // kolor linii, w każdym obiegu inny Canvas->MoveTo(i,i); // punkt początkowy trójkąta nr 2 Canvas->LineTo(i,512-i); // lewy bok Canvas->LineTo(512-i,512-i); // górny bok Canvas->LineTo(i,i); // przekątna } } //---------------------------------------------------------------------------
Rysowanie linii jest znacznie szybsze od rysowania pikseli.
Teraz pobawimy się rysowaniem linii. Na początek wielokąty foremne. Tworzymy je, wyznaczając punkty wierzchołkowe i łącząc te punkty za pomocą linii. Punkty wierzchołkowe można wyznaczyć w prosty sposób za pomocą funkcji trygonometrycznych. Wyobraźmy sobie, że chcemy narysować sześciokąt foremny. Rysujemy okrąg o środku w punkcie (0,0) i o promieniu r:
Punkty (x,y) na okręgu wyliczamy wg wzoru:
Sześciokąt foremny zbudujemy, wyznaczając na obwodzie tego koła sześć równoodległych punktów:
Współrzędne tych punktów wyliczymy wg wzorów:
gdzie i = 0,1,2,...,5
Punkty łączymy liniami i powstaje sześciokąt foremny:
Taki wielokąt nie zostałby w całości narysowany w oknie aplikacji, ponieważ jego środek wypadłby w lewym górnym narożniku powierzchni Canvas. Dlatego wielokąt zwykle chcemy rysować o środku w punkcie Sx, Sy. W tym celu musimy dokonać drobnej korekty wzorów:
gdzie i = 0,1,2,...,5
Podane wzory można prosto rozszerzyć na wielokąt foremny o dowolnej liczbie boków n, n > 2:
gdzie i = 0,1,2,...,n-1
Dodatkowo możemy wprowadzić do wzorów kąt początkowy, który określi położenie punktu P0:
Nasze ostateczne wzory przyjmą zatem postać:
gdzie i = 0,1,2,...,n-1
Na podstawie tych wzorów napiszemy prostą aplikację, która w oknie aplikacji będzie rysowała zadany wielokąt foremny. Utwórz nowy projekt aplikacji w Borland C++ Builder. W oknie aplikacji umieść dwie etykiety tekstowe Label,, dwa pola edycyjne Edit oraz trzy przyciski Button. Poniżej podajemy własności dla poszczególnych elementów (do zmiany własności obiekt wybierasz na formie klikając go myszką lub w oknie Object TreeView, a następnie modyfikujesz jego własności w oknie Object Inspector):
Form1
BorderStyle
= bsSingle
Użytkownik nie będzie mógł zmieniać rozmiarów okna przez
przeciąganie myszką jego krawędzi.
Caption = Wielokaty foremne
Tytuł okna.
ClientHeight = 512
Wysokość obszaru graficznego okna. Taką wysokość będzie miała nasza
powierzchnia rysunkowa Canvas.
ClientWidth = 512
Szerokość obszaru graficznego okna.
Color = clWhite
Okienka nie muszą zawsze być szare.
Name = frmPolygons
Pod tą nazwą będzie dostępna w programie zmienna klasy naszego okna.
Position = poScreenCenter
Okienko aplikacji będzie się pojawiało na środku ekranu.
Label1
Left = 32
Name= lbl1
Top = 456
Label2
Left = 32
Name= lbl2
Top = 480
Edit1
Name = edtN
Text = 6
Początkowa liczba boków.
Top = 456
Edit2
Name = edtFi
Text = 0
Początkowy kąt obrotu.
Top = 480
Button1
Default =
true
Po naciśnięciu klawisza Enter ten przycisk będzie automatycznie
wybierany
Left = 256
Name = btnPaint
Top = 464
Button2
Left = 336
Name = btnClear
Top = 464
Button3
Left = 416
Name = btnClose
Top = 464
Interfejs naszej aplikacji jest gotowy:
Na początku programu dopisz fragmenty pokazane w kolorze czarnym:
//--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop #include "Unit1.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" #include <math.h> TfrmPolygons *frmPolygons; int n = 6; int fi = 0; //---------------------------------------------------------------------------
Teraz dodamy do niego obsługę zdarzeń. Wybierz frmPolygons i w Object Inspector kliknij zakładkę Events, a następnie kliknij dwukrotnie obok zdarzenia onPaint. Do utworzonej w edytorze funkcji obsługi zdarzenia wpisz poniższy kod:
void __fastcall TfrmPolygons::FormPaint(TObject *Sender) { const double PI2 = 6.2831853; // 2 pi int i,x,y; double f = PI2 * fi / 360; // wyznaczamy punkty na obwodzie koła o środku w punkcie (256,230) // i promieniu 200. Do pierwszego punktu przechodzimy poleceniem MoveTo(), // a pozostałe n punktów łączymy liniami za pomocą LineTo(). for(i = 0; i <= n; i++) { x = 256 + 200 * cos(f + i * PI2 / n); y = 230 + 200 * sin(f + i * PI2 / n); if(i) Canvas->LineTo(x,y); else Canvas->MoveTo(x,y); } Canvas->Pixels[x][y] = 0; // zamykamy ostatni bok z pierwszym }
W Object TreeView kliknij dwukrotnie btnPaint i do funkcji obsługi kliknięcia wpisz:
void __fastcall TfrmPolygons::btnPaintClick(TObject *Sender) { n = StrToInt(edtN->Text); // odczytujemy liczbę boków fi = StrToInt(edtFi->Text); // odczytujemy kąt obrotu FormPaint(Sender); // rysujemy wielokąt }
To samo zrób z btnClear i wpisz do jego procedury obsługi kliknięcia kod:
void __fastcall TfrmPolygons::btnClearClick(TObject *Sender) { Invalidate(); }
Funkcja Invalidate() powoduje unieważnienie treści okna, co z kolei spowoduje jego wyczyszczenie i przerysowanie od nowa, czyli wywołanie funkcji obsługi zdarzenia onPaint. Ponieważ najpierw treść okna jest czyszczona, to na jego powierzchni graficznej zostaje narysowany ostatnio wybrany wielokąt.
W podany powyżej sposób utwórz funkcję obsługi zdarzenia onClick dla btnClose i wprowadź do niej kod:
void __fastcall TfrmPolygons::btnCloseClick(TObject *Sender) { Close(); }
Aplikacja jest gotowa.
Bardzo ciekawe figury powstają, gdy wszystkie wierzchołki wielokąta połączymy odcinkami. Wpisz do funkcji obsługi zdarzenia onPaint poniższy kod:
void __fastcall TfrmPolygons::FormPaint(TObject *Sender) { const double PI2 = 6.2831853; // 2 pi int i,j,x1,y1,x2,y2; double f = PI2 * fi / 360; for(i = 0; i < n; i++) { x1 = 256 + 200 * cos(f + i * PI2 / n); // punkt startowy linii y1 = 230 + 200 * sin(f + i * PI2 / n); for(j = i + 1; j < n; j++) { x2 = 256 + 200 * cos(f + j * PI2 / n); // kolejne punkty końcowe y2 = 230 + 200 * sin(f + j * PI2 / n); Canvas->MoveTo(x1,y1); Canvas->LineTo(x2,y2); } } }
W oknie mogą wtedy powstawać takie oto "dzieła":
Kolejna prosta aplikacja będzie rysowała prostokąty i elipsy. Są to figury, które posiadają wypełnienie. Do sterowania kolorem wypełnienia mamy własność:
Canvas -> Brush -> Color
Kody kolorów dla wypełnienia określa się identycznie jak dla pikseli lub
linii.
Dodatkowo wykorzystamy prosty obiekt TRect definiujący prostokąt na powierzchni graficznej. Prostokąt definiujemy za pomocą parametrów przekazanych do jego konstruktora:
TRect r(left,top,right,bottom);
Konstruktor jest specjalną funkcją składową obiektu, która może być wywoływana w momencie tworzenia danego obiektu. Zadaniem konstruktora jest odpowiednie zainicjowanie wszystkich pól danych obiektu. Przy powyższej definicji otrzymujemy obiekt prostokąta, który definiuje pewien obszar na powierzchni graficznej. Parametry są następujące:
left | - | położenie lewej krawędzi |
top | - | położenie górnej krawędzi |
right | - | o 1 więcej niż położenie prawej krawędzi |
bottom | - | o 1 więcej niż położenie dolnej krawędzi (pamiętaj, że współrzędne graficzne na osi y rosną w dół) |
Do rysowania prostokątów używamy funkcji:
Canvas -> Rectangle(r);
gdzie r jest obiektem prostokąta.
Do rysowania elips używamy funkcji:
Canvas -> Ellipse(r);
gdzie r jest prostokątem opisującym elipsę.
Utwórz nową aplikację w Borland C++ Builder. Na oknie głównym umieść dwa przyciski Button. Zmień własności wg poniższej listy:
Frame1
BorderStyle = bsSingle
Caption = Kształty
ClientHeight = 512
ClientWidth = 512
Name = frmShapes
Position = poScreenCenter
Button1
Left = 8
Name = btnClear
Top = 472
Button2
Left = 88
Name = btnClose
Top = 472
Utwórz dla okna funkcję obsługi zdarzenia onMouseDown (w Object TreeView wybierz frmShapes, w Object Inspector wybierz zakładkę Events i kliknij dwukrotnie po prawej stronie zdarzenia onMouseDown). Zdarzenie to powstaje, gdy użytkownik kliknie w obiekt lewym lub prawym przyciskiem myszki. Powstanie następująca funkcja:
void __fastcall TfrmShapes::FormMouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { }
W parametrach funkcja otrzymuje:
Button | - | określa naciśnięty przycisk myszki: mbLeft - lewy mbRight - prawy |
Shift | - | zbiór określający użyte klawisze myszki oraz Alt, Shift i Ctrl na klawiaturze, Tutaj z tego nie korzystamy. |
X, Y | - | współrzędne kursora myszki w momencie powstania zdarzenia. Współrzędne odnoszą się do pozycji na powierzchni Canvas obiektu. |
Do funkcji wpisz następujący kod:
void __fastcall TfrmShapes::FormMouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { int rx = 10 + rand() % 60; // wybieramy losowe szerokości int ry = 10 + rand() % 60; TRect r(X-rx,Y-ry,X+rx,Y+ry); // tworzymy prostokąt r o środku w X,Y Canvas->Brush->Color = RGB(rand()%256,rand()%256,rand()%256); // kolor wypełnienia Canvas->Pen->Color = RGB(rand()%256,rand()%256,rand()%256); // kolor linii if(Button == mbLeft) Canvas->Rectangle(r); // dla lewego przycisku prostokąt else if(Button == mbRight) Canvas->Ellipse(r); // a dla prawego elipsa }
Teraz kliknij dwukrotnie w Object TreeView na btnClear i w edytorze wpisz kod:
void __fastcall TfrmShapes::btnClearClick(TObject *Sender) { Invalidate(); }
Wywołanie funkcji Invalidate() powoduje unieważnienie treści okna, które zostanie narysowane od nowa, mażąc narysowaną wcześniej grafikę.
Kliknij dwukrotnie w Object TreeView na btnClose i w edytorze wpisz kod:
void __fastcall TfrmShapes::btnCloseClick(TObject *Sender) { Close(); }
Po uruchomieniu aplikacji kliknięcie lewym przyciskiem w okienko powoduje narysowanie prostokąta, a kliknięcie przyciskiem prawym powoduje narysowanie elipsy. Ponieważ kolory wypełnienia i linii są pseudolosowe, za każdym razem będą zwykle inne. Również wielkość prostokątów i elips będzie się zmieniała.
Funkcja składowa:
Canvas -> FrameRect(r);
gdzie r jest prostokątem
Rysuje ramkę o pustym wnętrzu. Do rysowania linii ramki wykorzystywany jest obiekt Canvas -> Brush.
Elipsę bez wnętrza narysujemy za pomocą funkcji:
Canvas -> Arc(x1,y1,x2,y2,x3,y3,x4,y4);
Funkcja ta wymaga przekazania jej współrzędnych czterech punktów:
Punkt x3,y3 oraz środek elipsy wyznaczają linię, której przecięcie z elipsą określa punkt startowy, od którego będzie rysowana elipsa. Kierunek rysowania jest przeciwny do kierunku ruchu wskazówek zegara.
Punkt x4,y4 oraz środek elipsy wyznaczają linię, której przecięcie z elipsą określi punkt końcowy jej linii. Jeśli punkty x3,y3 i x4,y4 są różne, to będzie narysowany tylko fragment elipsy. Jeśli są takie same, elipsa zostanie narysowana w całości.
W Naszym programie zastąp funkcję obsługi zdarzenia onMouseDown poniższym kodem:
void __fastcall TfrmShapes::FormMouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { int rx = 10 + rand() % 60; int ry = 10 + rand() % 60; TRect r(X-rx,Y-ry,X+rx,Y+ry); Canvas->Brush->Color = RGB(rand()%256,rand()%256,rand()%256); // kolor ramki Canvas->Pen->Color = RGB(rand()%256,rand()%256,rand()%256); // kolor elipsy if(Button == mbLeft) Canvas->FrameRect(r); if(Button == mbRight) Canvas->Arc(r.Left,r.Top,r.Right,r.Bottom,r.Left,r.Bottom,r.Left,r.Bottom); }
Canvas
Canvas -> Pixels[x][y]
Canvas -> MoveTo(x,y);
Canvas -> LineTo(x,y);
Canvas -> Pen -> Color
Canvas -> Brush -> Color
Canvas -> Rectangle(r);
Canvas->Pen->Color
Canvas->Brush->Color.
Canvas -> Ellipse(r);
Canvas->Pen->Color
Canvas->Brush->Color.
Canvas -> FrameRect(r);
Canvas->Brush->Color.
Canvas -> Arc(x1,y1,x2,y2,x3,y3,x4,y4);
Canvas->Pen->Color.
I Liceum Ogólnokształcące |
Pytania proszę przesyłać na adres email: i-lo@eduinf.waw.pl
W artykułach serwisu są używane cookies. Jeśli nie chcesz ich otrzymywać,
zablokuj je w swojej przeglądarce.
Informacje dodatkowe