CIEKAWOSTKI
W tym dziale postanowiłem zamieszczać przykłady ciekawych, acz mało praktycznych zastosowań języka c++. Tak więc porady, które się tutaj znajdują wnoszą raczej niewielki wkład w programowanie z wykorzystaniem kompilatora Borland C++ Builder.
Konwertowanie klasy TComponent na łańcuch znaków i odwrotnie
Czym jest klasa
TComponent nie muszę chyba nikomu wyjaśniać, ponieważ programując w BCB nieustannie się z niej korzysta, wspomnę tylko, że wszystkie komponenty wywodzą się z klasy TComponent. Istnieje możliwość odczytania informacji o komponencie, czyli o wszystkich jego właściwościach jakie zostały wykorzystane w utworzonym programie. Żeby się o tym przekonać stwórzmy prosty program, wykorzystamy do tego trzy komponenty: Memo1, Button1 i Button2. Po rozmieszczeniu ich na formularzu, przechodzimy do pliku źródłowego i definiujemy w nim funkcję ComponentToString (nazwa funkcji jest dowolna):
// Plik źródłowy np. Unit1.cpp //--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop
#include "Unit1.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- AnsiString ComponentToString(TComponent *c) { AnsiString as; TMemoryStream*
pms = new TMemoryStream(); TStringStream* pss = new TStringStream(as);
try { pms->WriteComponent(c); pms->Seek(0, soFromBeginning); ObjectBinaryToText(pms, pss); pss->Seek(0, soFromBeginning); as = pss->DataString; } catch(...) { ShowMessage("Błąd strumienia danych."); }
delete pms; delete pss; return as; } //--------------------------------------------------------------------------- |
Funkcje odczytuje dane z pamięci i konwertuje je na łańcuch znaków. Żeby zobaczyć jak działa wywołamy ją w zdarzeniu OnClick dla przycisku Button1, przy czym odczytamy informacje o komponencie Button2 i zapiszemy je w obiekcie Memo1:
// Plik źródłowy np. Unit1.cpp ...... //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { Memo1->Text = ComponentToString(Button2); } //--------------------------------------------------------------------------- |
Powinno ukazać się coś mniej więcej takiego jak na poniższym rysunku:

Tak odczytane informacje można zmienić i przekonwertować ponownie, albo raczej przekazać ponownie do wybranego obiektu, w tym przypadku do obiektu Button2. W tym celu napiszemy funkcję StringToComponent i przekażemy jej jako argumentu odwołanie do komponentu Button2 oraz zawartość obiektu Memo1. Przed wywołaniem funkcji w zdarzeniu OnClick dla przycisku Button2 proponuję dokonać małych zmian w opisie obiektu, w oknie edycji Memo1, na można zmienić wartość Left na 240, powinno to spowodować przesunięcie obiektu Button2 o dodatkowe 120 pikseli w lewo:
// Plik źródłowy np. Unit1.cpp ...... //--------------------------------------------------------------------------- void StringToComponent(TComponent *c, AnsiString as) { TMemoryStream* pms = new TMemoryStream(); TStringStream* pss = new TStringStream(as);
try { ObjectTextToBinary(pss, pms); pms->Seek(0, soFromBeginning); } catch(...) { ShowMessage("Błąd strumienia danych"); }
pms->ReadComponent(c); delete pms; delete pss; } //--------------------------------------------------------------------------- void __fastcall TForm1::Button2Click(TObject *Sender) { StringToComponent(Button2, Memo1->Text); }
//--------------------------------------------------------------------------- |
Nie znalazłem, żadnego praktycznego zastosowania dla tych funkcji, ale kto wie...
...powrót do menu. 
Ograniczenie obszaru przemieszczania się dla wskaźnika myszy.
Istnieje pewna funkcja API -
ClipCursor(const tagRECT *lpRect)
- umożliwiająca wprowadzenie ograniczenia obszaru po którym może poruszać się kursor myszy. Już na samym początku wyjaśnię, że poddając ograniczeniom wybrany obszar, trzeba jako punkt odniesienia brać cały obszar ekranu, a nie obszar formularza (np Form1). Funkcję klip należy wywołać w jakimś zdarzeniu, przy czym funkcja nie zadziała jeżeli spróbujemy wywołać ją w zdarzeniach wywoływanych przy uruchamianiu aplikacji (np OnShow, OnCreate). W sytuacji gdy chcemy ustawić obszar tuż po uruchomieniu programu należy to zrobić w zdarzeniu OnPaint dla formularza poza tym takie zdarzenia jak maksymalizacja i ponowne przywrócenie formularza spowodują
wyłączenie funkcji, dlatego należy powtórzyć ją w zdarzeniu OnResize.
W przykładzie ograniczę obszar przemieszczania kursora myszy dla całego formularza, funkcja zostanie wywołana w zdarzeniu OnPAint dla formularza:
// Plik źródłowy np. Unit1.cpp //--------------------------------------------------------------------------- void __fastcall TForm1::FormPaint(TObject *Sender) { ClipCursor(&BoundsRect); } //--------------------------------------------------------------------------- |
W przykładzie posłużyłem się metodą BoundsRect wskazującą na cały obszar formularza, ale równie dobrze można do tego celu wykorzystać klasę TRect:
// Plik źródłowy np. Unit1.cpp //--------------------------------------------------------------------------- void __fastcall TForm1::FormPaint(TObject *Sender) { TRect R = Rect(Left, Top, Left + Width, Top + Height); ClipCursor(&R); } //--------------------------------------------------------------------------- |
Ograniczenia obszaru mogą dotyczyć konkretnego obiektu znajdującego się na formularzu, np obiektu Memo1:
// Plik źródłowy np. Unit1.cpp //--------------------------------------------------------------------------- void __fastcall TForm1::FormPaint(TObject *Sender) { TRect R = Rect(Left + Memo1->Left + 4, Top + Memo1->Top + 30, Left + Memo1->Left + Memo1->Width + 4, Top + Memo1->Top + Memo1->Height + 30); ClipCursor(&R); } //--------------------------------------------------------------------------- |
Funkcję wyłącza się przekazując jako argument wartość NULL:
// Plik źródłowy np. Unit1.cpp //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { ClipCursor(NULL); } //--------------------------------------------------------------------------- |
...powrót do menu. 
Rysowanie linii przerywanej poprzez określenie własnego stylu.
Niemalże każdy wie jak narysować linię z wykorzystaniem klasy TCanvas, więc nie będę tutaj tego opisywał, skupię się na liniach przerywanych, ale takich w których można określić własny styl kreskowania. Linie kreskowaną można narysować na wiele sposobów poprzez określenie stylu pióra, dostępne są następujące style kreskowania:
- psDot
- psDash
- psDashDot
- psDashDotDot
Gwoli przypomnienia dodam tylko że do narysowania ciągłej linii należy ustawić styl pióra na psSolid. Narysujmy teraz linię przekątną na formularzu (np Form1) z wykorzystaniem dowolnego stylu, np psDasDot:
// Plik źródłowy np. Unit1.cpp //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { Canvas->Pen->Style = psDashDot; Canvas->MoveTo(0, 0); Canvas->LineTo(ClientWidth, ClientHeight); } //--------------------------------------------------------------------------- |
A teraz zróbmy to samo z tą jednak różnicą, że opracujemy własny styl kreskowania:
// Plik źródłowy np. Unit1.cpp //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { LOGBRUSH lbrush = { BS_SOLID, RGB(0,0,0), NULL}; DWORD userstyle[] = {2, 2, 4, 4, 8, 8, 16, 16, 32, 32};
Canvas->Pen->Handle = ExtCreatePen(PS_COSMETIC | PS_USERSTYLE, 1, &lbrush, 10, userstyle); Canvas->MoveTo(0, 0); Canvas->LineTo(ClientWidth, ClientHeight); } //---------------------------------------------------------------------------
|
Klucz odpowiedzialny za kreskowanie został zaznaczony na żółto. W przedstawionym przykładzie sposób kreskowania i odstęp między liniami, jak też same linie będą się wydłużały. Liczby podzielone są na grupy, każda grupa składa się z dwóch liczb z których pierwsza określa długość linii, natomiast druga określa przerwę pomiędzy liniami.
...powrót do menu. 
Wyliczanie okien.
Pisząc o wyliczaniu okien mam na myśli użycie funkcji API, która pozwala na pobranie nazw wszystkich aktualnie otwartych okien w systemie oraz na pobranie szczegółów dotyczących używanych klas. Zdecydowałem się na umieszczenie tej porady w dziale ciekawostki ponieważ nie znalazłem dla niej praktycznego zastosowania, aczkolwiek po zmodyfikowaniu, funkcję użytą przy wyliczaniu okien można wykorzystać do zamykania programów uruchomionych w systemie, o ile znamy nazwę jego okna, ale o tym w innej poradzie.
Tak więc, bez zbędnego zagłębiania się w szczegóły, tworzymy nowy projekt i umieszczamy na formularzu dwa obiekty typu TlistView i TButton. Właściwość ViewStyle obiektu ListView1 zmieniamy na vsReport, a we właściwości Columns tworzymy dwie kolumny o nazwach 'Tekst
okna' i 'Nazwa klasy'.

Następnie w pliku nagłówkowym przed deklaracją klasy umieszczamy deklarację funkcji EnumWindowProc (nazwa funkcji jest dowolna):
// Plik nagłówkowy np. Unit1.h //--------------------------------------------------------------------------- #ifndef Unit1H #define Unit1H //--------------------------------------------------------------------------- #include <Classes.hpp> #include <Controls.hpp> #include <StdCtrls.hpp> #include <Forms.hpp> #include <ComCtrls.hpp> //--------------------------------------------------------------------------- bool CALLBACK EnumWindowsProc(HWND hWnd, TListView *ListView); class TForm1 : public TForm { __published: // IDE-managed Components TListView *ListView1; TButton *Button1; void __fastcall Button1Click(TObject *Sender); private: // User declarations public: // User declarations __fastcall
TForm1(TComponent* Owner); }; //--------------------------------------------------------------------------- extern PACKAGE TForm1 *Form1; //--------------------------------------------------------------------------- #endif |
Następnie przechodzimy do pliku źródłowego i umieszczamy w nim definicję utworzonej właśnie funkcji:
// Plik źródłowy np. Unit1.cpp //--------------------------------------------------------------------------- bool CALLBACK EnumWindowsProc(HWND hWnd, TListView *ListView) { char WindowName[80], ClassName[80];
GetWindowText(hWnd, WindowName, 80); GetClassName(hWnd, ClassName, 80); ListView->Items->Add(); int i = ListView->Items->Count-1; ListView->Items->Item[i]->Caption = AnsiString(WindowName); ListView->Items->Item[i]->SubItems->Add(AnsiString(ClassName)); ListView->Items->Item[i]->Update(); return true; } //--------------------------------------------------------------------------- |
Teraz pozostało już tylko w zdarzeniu OnClick dla przycisku Button1 wywołać funkcję z odpowiednimi parametrami:
// Plik źródłowy np. Unit1.cpp //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { ListView1->Items->Clear(); EnumChildWindows(GetDesktopWindow(),(WNDENUMPROC)EnumWindowsProc, (LPARAM)ListView1); EnumWindows((WNDENUMPROC)EnumWindowsProc,(LPARAM)ListView1); EnumDesktopWindows(NULL,(WNDENUMPROC)EnumWindowsProc,(LPARAM)ListView1); } //--------------------------------------------------------------------------- |
I to by było wszystko na ten temat, a oto wynik działania programu:

...powrót do menu. 
Mieszanie grafiki, czyli psucie obrazka.
Pod tym nieco tajemniczo brzmiącym nagłówkiem kryje się tak naprawdę porada spłodzona przez nudę. Otóż nudząc się pewnego razu (są takie dni gdy nic się nie chce robić) zacząłem rozważać problem takiego pomieszania dowolnej grafiki, żeby uczynić z niej nieczytelny obrazek, czyli coś jak szyfrowanie. Zaprzągłem do tego celu funkcję ScanLine jednak okazała się ona - w przypadku tego zadania - mało praktyczna, więc w efekcie stworzyłem własną funkcję, która uczyniła to zadanie bardzo prostym do wykonania.
To tyle jeśli chodzi o wstęp, zanim jednak dalej zagłębię się w ten temat proponuję przyjrzeć się dwóm zamieszczonym niżej obrazkom, otóż pomimo iż już na pierwszy rzut oka różnią się one od siebie bardzo to jednak zawierają dokładnie to samo tylko, że w drugim obrazku linie grafiki zostały pomieszane:

Żeby osiągnąć taki efekt wykorzystałem klasę TCanvas i dwie z jej funkcji CopyRect i Draw. Stworzyłem funkcję SetMozaika (nazwa jest dowolna), pobierającą trzy argumenty: bitmapę - na której wykonujemy operację, długość tej bitmapy o raz numer linii poddawanej szyfrowaniu. Funkcja jest tak skonstruowana, że nie potrzebuje deklaracji w pliku nagłówkowym, wystarczy sama definicja (która jest również deklaracją) w pliku źródłowym:
// Plik źródłowy np. Unit1.cpp //--------------------------------------------------------------------------- Graphics::TBitmap *SetMozaika(Graphics::TBitmap *Bmp, int Width, int Count) { Graphics::TBitmap *Tmp = new Graphics::TBitmap; Tmp->Width = Width; Tmp->Height = 1;
Tmp->Canvas->CopyRect(Rect(0, 0, Width, 1), Bmp->Canvas, Rect(0, Count, Width, Count + 1));
return Tmp; } //--------------------------------------------------------------------------- |
Jak widać funkcja odczytuje linie grafiki o długości równej długości tej grafiki i szerokości równej 1. Funkcja zwraca wartość typu TBitmap.
W celu "pomieszania" grafiki użyłem pętli, która w każdym obiegu wykonuje operacje na 15 liniach grafiki. W celu sprawdzenia jak to działa proponuję umieścić na formularzu dwa obiekty typu TImage - Image1 i Image2, oraz trzy przyciski typu TButton. Do obiektu Image1 wczytujemy dowolną grafikę w formacie *.bmp i tu bardzo istotne jest, żeby szerokość grafiki była podzielna przez liczbę 15 bez reszty (to bardzo ułatwi zadanie), w przeciwnym razie przy deszyfrowaniu bitmapy na dole rysunku pojawią się źle zdeszyfrowane linie. Następnie w zdarzeniu OnClick dla przycisku Button1 umieszczamy pętlę szyfrującą grafikę:
// Plik źródłowy np. Unit1.cpp //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { Screen->Cursor = crHourGlass; Image2->Width = Image1->Width; Image2->Height = Image1->Height; int H = Image1->Height; for(int i = 0; i < H; i += 15) { Image2->Canvas->Draw(0, H - i - 15, SetMozaika(Image1->Picture->Bitmap, Image1->Width, i)); Image2->Canvas->Draw(0, H - i - 14, SetMozaika(Image1->Picture->Bitmap, Image1->Width, i + 14)); Image2->Canvas->Draw(0,
H - i - 13, SetMozaika(Image1->Picture->Bitmap, Image1->Width, i + 1)); Image2->Canvas->Draw(0, H - i - 12, SetMozaika(Image1->Picture->Bitmap, Image1->Width, i + 9)); Image2->Canvas->Draw(0, H - i - 11, SetMozaika(Image1->Picture->Bitmap, Image1->Width, i + 4));
Image2->Canvas->Draw(0, H - i - 10, SetMozaika(Image1->Picture->Bitmap, Image1->Width, i + 13)); Image2->Canvas->Draw(0, H - i - 9, SetMozaika(Image1->Picture->Bitmap, Image1->Width,
i + 2)); Image2->Canvas->Draw(0, H - i - 8, SetMozaika(Image1->Picture->Bitmap, Image1->Width, i + 8)); Image2->Canvas->Draw(0, H - i - 7, SetMozaika(Image1->Picture->Bitmap, Image1->Width, i + 12)); Image2->Canvas->Draw(0, H - i - 6, SetMozaika(Image1->Picture->Bitmap, Image1->Width, i + 3));
Image2->Canvas->Draw(0, H - i - 5, SetMozaika(Image1->Picture->Bitmap, Image1->Width, i + 6)); Image2->Canvas->Draw(0,
H - i - 4, SetMozaika(Image1->Picture->Bitmap, Image1->Width, i + 11)); Image2->Canvas->Draw(0, H - i - 3, SetMozaika(Image1->Picture->Bitmap, Image1->Width, i + 5)); Image2->Canvas->Draw(0, H - i - 2, SetMozaika(Image1->Picture->Bitmap, Image1->Width, i + 10)); Image2->Canvas->Draw(0, H - i - 1, SetMozaika(Image1->Picture->Bitmap, Image1->Width, i + 7)); } Image2->Invalidate(); Screen->Cursor = crDefault; }
//--------------------------------------------------------------------------- |
Po naciśnięciu przycisku w obiekcie Image2 pojawi się zaszyfrowana grafika z obiektu Image1. Zapiszmy zawartość obiektu Image2 do pliku "Convert.bmp" wywołując odpowiednią funkcję w zdarzeniu OnClick dla przycisku Button2:
// Plik źródłowy np. Unit1.cpp //--------------------------------------------------------------------------- void __fastcall TForm1::Button2Click(TObject *Sender) { Image2->Picture->SaveToFile(ExtractFilePath(Application->ExeName) + "Convert.bmp"); } //--------------------------------------------------------------------------- |
Teraz dla odmiany umieśćmy w obiekcie Image1 zaszyfrowaną grafikę z pliku "Convert.bmp". żeby zdeszyfrować grafikę należy umieścić w zdarzeniu OnClick dla przycisku Button3 taką samą pętlę z odwrotnymi instrukcjami:
// Plik źródłowy np. Unit1.cpp //--------------------------------------------------------------------------- void __fastcall TForm1::Button3Click(TObject *Sender) { Screen->Cursor = crHourGlass; Image2->Width = Image1->Width; Image2->Height = Image1->Height;
int H = Image1->Height; for(int i = 0; i < H; i += 15) { Image2->Canvas->Draw(0, i, SetMozaika(Image1->Picture->Bitmap, Image1->Width, H - i - 15)); Image2->Canvas->Draw(0, i + 14, SetMozaika(Image1->Picture->Bitmap, Image1->Width, H - i - 14));
Image2->Canvas->Draw(0, i + 1, SetMozaika(Image1->Picture->Bitmap, Image1->Width, H - i - 13)); Image2->Canvas->Draw(0, i + 9, SetMozaika(Image1->Picture->Bitmap, Image1->Width, H - i - 12)); Image2->Canvas->Draw(0, i + 4, SetMozaika(Image1->Picture->Bitmap, Image1->Width, H - i - 11));
Image2->Canvas->Draw(0, i + 13, SetMozaika(Image1->Picture->Bitmap, Image1->Width, H - i - 10)); Image2->Canvas->Draw(0, i + 2, SetMozaika(Image1->Picture->Bitmap,
Image1->Width, H - i - 9)); Image2->Canvas->Draw(0, i + 8, SetMozaika(Image1->Picture->Bitmap, Image1->Width, H - i - 8)); Image2->Canvas->Draw(0, i + 12, SetMozaika(Image1->Picture->Bitmap, Image1->Width, H - i - 7)); Image2->Canvas->Draw(0, i + 3, SetMozaika(Image1->Picture->Bitmap, Image1->Width, H - i - 6));
Image2->Canvas->Draw(0, i + 6, SetMozaika(Image1->Picture->Bitmap, Image1->Width, H - i - 5)); Image2->Canvas->Draw(0,
i + 11, SetMozaika(Image1->Picture->Bitmap, Image1->Width, H - i - 4)); Image2->Canvas->Draw(0, i + 5, SetMozaika(Image1->Picture->Bitmap, Image1->Width, H - i - 3)); Image2->Canvas->Draw(0, i + 10, SetMozaika(Image1->Picture->Bitmap, Image1->Width, H - i - 2)); Image2->Canvas->Draw(0, i + 7, SetMozaika(Image1->Picture->Bitmap, Image1->Width, H - i - 1)); } Image2->Invalidate(); Screen->Cursor = crDefault; }
//--------------------------------------------------------------------------- |
Jak widać strasznie tutaj dużo kodu, a pewne elementy wciąż się powtarzają, więc można to trochę zoptymalizować. Niżej zamieszczam kompletny kod tego prostego szyfrowania, dodałem dwie dodatkowe funkcje Szyfruj i DeSzyfruj (nazwy dowolne), które pozwalają na szyfrowanie obrazka według zadanego klucza:
// Plik źródłowy np. Unit1.cpp //--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop
#include "Unit1.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- Graphics::TBitmap *SetMozaika(Graphics::TBitmap *Bmp, int Width, int
Count) { Graphics::TBitmap *Tmp = new Graphics::TBitmap; Tmp->Width = Width; Tmp->Height = 1;
Tmp->Canvas->CopyRect(Rect(0, 0, Width, 1), Bmp->Canvas, Rect(0, Count, Width, Count + 1));
return Tmp; } //--------------------------------------------------------------------------- void __fastcall Szyfruj(TImage *Img1, TImage *Img2, String Key, int Line) { int
H = Img1->Height; for(int i = 1; i <= 15; i++) { int x = i * 2; int k = StrToInt(Key.SubString(x - 1, 2)); Img2->Canvas->Draw(0, H - Line - (16 - i), SetMozaika(Img1->Picture->Bitmap, Img1->Width, Line + k)); } } //--------------------------------------------------------------------------- void __fastcall DeSzyfruj(TImage *Img1, TImage *Img2, String Key, int Line) { int H = Img1->Height; for(int
i = 1; i <= 15; i++) { int x = i * 2; int k = StrToInt(Key.SubString(x - 1, 2)); Img2->Canvas->Draw(0, Line + k, SetMozaika(Img1->Picture->Bitmap, Img1->Width, H - Line - (16 - i))); } } //---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender) { Screen->Cursor = crHourGlass; Image2->Width = Image1->Width; Image2->Height = Image1->Height; int H = Image1->Height; for(int i = 0; i < H; i += 15) { Szyfruj(Image1, Image2, "001401090413020812030611051007", i); } Image2->Invalidate(); Screen->Cursor = crDefault; } //--------------------------------------------------------------------------- void __fastcall TForm1::Button2Click(TObject *Sender) { Image2->Picture->SaveToFile("Convert.bmp"); } //--------------------------------------------------------------------------- void __fastcall TForm1::Button3Click(TObject *Sender) { Screen->Cursor
= crHourGlass; Image2->Width = Image1->Width; Image2->Height = Image1->Height; int H = Image1->Height; for(int i = 0; i < H; i += 15) { DeSzyfruj(Image1, Image2, "001401090413020812030611051007", i); } Image2->Invalidate(); Screen->Cursor = crDefault; } //--------------------------------------------------------------------------- |
Kod szyfrujący składa się z ciągu 15 liczb pisanych w parach po dwie cyfry i w przykładzie są to: 00, 14, 01, 09, 04, 13, 02, 08, 12, 03, 06, 11, 05, 10, 07. Oczywiście można stosować dowolny ciąg znaków jednak - co jest zrozumiałe samo przez się - należy do szyfrowania i deszyfrowania używać tych samych kluczy. Klucz musi składać się z trzydziestu cyfr pogrupowanych w liczby po dwie cyfry. Użyte liczby nie mogą powtarzać się w kluczu i muszą zawierać się w przedziale od 0 do 14, a to chyba daje ponad 3000 kombinacji, ale pewien nie jestem.
WAŻNA UWAGA!
W tej poradzie nie umieszczałem deklaracji funkcji w pliku nagłówkowym, jednak w takim wypadku, gdy definicja funkcji nie posiada swojej deklaracji istotna staje się kolejność umieszczania funkcji i zdarzeń, czyli funkcja musi być umieszczona przed zdarzeniem w którym jest wywoływana w przeciwnym razie zdarzenie (np. OnClick dla przycisku Button) nie będzie "widziało funkcji", np:
// Plik źródłowy np. Unit1.cpp //--------------------------------------------------------------------------- void __fastcall Funkcja1(void) { Funkcja2(10); // to jest źle ponieważ Funkcja2 jest zdefiniowana po Funkcji1. } //--------------------------------------------------------------------------- void __fastcall Funkcja2(int x) { int i = x++; } //--------------------------------------------------------------------------- void __fastcall TForm1::Button2Click(TObject *Sender) { Funkcja1(); // to jest dobrze ponieważ Funkcja1 jest zdefiniowana przed wywołaniem jej w tym zdarzeniu.
} //--------------------------------------------------------------------------- |
...powrót do menu. 
Pomiar czasu wykonywania zadania przez kod programu.
Często tworząc jakiś program umieszczamy w nim kody, które wykonują zadane
działania w jakimś nieznanym nam czasie, mogą to być np. pętle for wykonujące
działania na bardzo dużych liczbach. Istnieje prosty sposób na sprawdzenie ile
czasu zajmuje programowi wykonanie określonego zadania, a można posłużyć się w
tym celu mało znaną funkcją clock() z biblioteki time.h. W
przykładzie do pomiaru różnicy czasu między początkiem i końcem zadania posłużę
się zmienną typu clock_t pochodzącą z tej samej biblioteki, ale równie
dobrze można posłużyć się zmienną typu int:
// Plik źródłowy np. Unit1.cpp //---------------------------------------------------------------------------
#include <time.h>
#include <stdio.h>
void __fastcall TForm1::Button1Click(TObject *Sender)
{
clock_t start, end;
start = clock();
char Buf[255];
for(int i = 0; i < 1000000000; i++){;}
end = clock();
sprintf(Buf, "Czas wykonywania
zadania: %f", (end - start) / CLK_TCK);
Edit1->Text = (String)Buf;
} //--------------------------------------------------------------------------- |
Jeżeli nie wierzycie, że ten kod mierzy czas wykonywania się pętli to
proponuję inny prosty przykład z wykorzystaniem funkcji Sleep wstrzymującej
wykonywanie kodu na np. 2 sekundy:
// Plik źródłowy np. Unit1.cpp //---------------------------------------------------------------------------
#include <time.h>
#include <stdio.h>
void __fastcall TForm1::Button1Click(TObject *Sender)
{
clock_t start, end;
start = clock();
char Buf[255];
Sleep(2000);
end = clock();
sprintf(Buf, "Czas wstrzymania:
%f", (end - start) / CLK_TCK);
Edit1->Text = (String)Buf;
} //--------------------------------------------------------------------------- |
...powrót do menu. 
Zakrywanie ekranu bitmapą.
Dla tej porady nie znalazłem żadnego
praktycznego zastosowania, może co najwyżej posłużyć do zabawy, nie ma to nic
wspólnego ze zmianą tapety pulpitu, sztuczka polega na przysłanianiu całego
pulpitu i znajdujących się na nim okien grafiką, zmiany nie są trwałe i tak np.
przesunięcie jakiegoś okna odkrywa kawałek pulpitu, ale ruch innego okna znów
zakrywa pulpit i okna grafiką. Dzieje się tak dopóki nasza aplikacja pozostaje
aktywna.
// w pliku
nagłówkowym np. Unit1.h
public:
TWndMethod OldScreen;
Graphics::TBitmap *Bmp;
void __fastcall NewScreen(TMessage &Msg);
void __fastcall
WMCtlColorEdit(TMessage &Msg);
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(WM_CTLCOLOREDIT, TMessage, WMCtlColorEdit)
END_MESSAGE_MAP(TForm) |
// Plik źródłowy np. Unit1.cpp //---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
OldScreen = this->WindowProc;
this->WindowProc = NewScreen;
Bmp = new Graphics::TBitmap;
Bmp->LoadFromFile(ExtractFilePath(ParamStr(0)) +
"obrazek.bmp");
} //---------------------------------------------------------------------------
void __fastcall TForm1::NewScreen(TMessage &Msg)
{
if(Msg.Msg == WM_PAINT || Msg.Msg == WM_SETFOCUS)
InvalidateRect(GetDC(0), NULL, false);
OldScreen(Msg);
if(Msg.Msg == WM_ERASEBKGND)
{
HDC Hdc = GetDC(0);
StretchBlt(Hdc, 0, 0, Screen->Width, Screen->Height, Bmp->Canvas->Handle,
0, 0, Bmp->Width, Bmp->Height, SRCCOPY);
Msg.Result = 0;
return;
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::WMCtlColorEdit(TMessage &Msg)
{
if((HWND)Msg.LParam == GetDC(0))
{
HDC Hdc = (HDC)Msg.WParam;
::SetBkMode(Hdc, TRANSPARENT);
Msg.Result = (LONG)this->Brush->Handle;
}
else TForm::Dispatch(&Msg);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender,
TCloseAction &Action)
{
this->WindowProc = OldScreen;
}
//--------------------------------------------------------------------------- |
...powrót do menu. 