-
Okno seznamu a kombinovan² ovladaΦ majφ styly nazvanΘ Owner draw,
co╛ znamenß, ╛e mφsto standardnφ metody zobrazovßnφ textu prvk∙ v ovladaΦi
je pou╛ito vlastnφ zobrazovßnφ prvk∙. ╚astΘ pou╛itφ ovladaΦe s vlastnφm
(u╛ivatelsk²m) zobrazovßnφm, je v p°φpad∞ pou╛itφ grafiky mφsto textu nebo
spoleΦn∞ s textem. V╣echny ovladaΦe s vlastnφm zobrazovßnφm obsahujφ seznam
prvk∙. Implicitn∞ tyto seznamy jsou seznamy °et∞zc∙, kterΘ se zobrazujφ
jako text. Ke ka╛dΘmu prvku v seznamu m∙╛eme p°i°adit objekt, Φφm╛ si usnadnφme
urΦovßnφ, kter² objekt kreslit. Obecn∞ p°i pou╛φvßnφ ovladaΦ∙ s vlastnφm
zobrazovßnφm provedeme tyto kroky: nastavφme styl vlastnφho zobrazovßnφ,
p°idßme k seznamu °et∞zc∙ grafickΘ objekty a zobrazφme prvky vlastnφm zobrazenφm.
Komponenty ListBox a ComboBox majφ vlastnost Style.
Tato vlastnost urΦuje, zda ovladaΦ pou╛φvß implicitnφ nebo vlastnφ zobrazovßnφ.
Komponenty m°φ╛ek majφ vlastnost DefaultDrawing k povolenφ nebo
zakßzßnφ implicitnφho zobrazovßnφ. Komponenty ListBox a ComboBox
majφ styly vlastnφho zobrazovßnφ nazvanΘ fixed a variable,
pro m°φ╛ky je v╛dy pou╛φvßn styl fixed (i kdy╛ jednotlivΘ °ßdky
a sloupce mohou mφt r∙znΘ rozm∞ry, je nutno urΦit velikost ka╛dΘ bu≥ky
p°ed zobrazenφm). V²znam t∞chto styl∙ je popsßn v nßsledujφcφ tabulce:
Styl vlastnφho zobrazovßnφ |
V²znam |
Fixed |
V╣echny prvky majφ stejnou v²╣ku urΦenou vlastnostφ ItemHeight. |
Variable |
V²╣ky jednotliv²ch prvk∙ se mohou li╣it a jsou urΦeny za b∞hu aplikace. |
Ka╛d² seznam °et∞zc∙ mß mo╛nost, mimo svΘho seznamu °et∞zc∙, obsahovat
i seznam objekt∙. Nap°. aplikace sprßvce soubor∙ m∙╛e obsahovat spoleΦn∞
s pφsmeny jednotek i bitovΘ mapy indikujφcφ typ jednotek. K tomu je zapot°ebφ
p°idat k aplikaci po╛adovanΘ obrßzky a odkazy na n∞ vlo╛it do seznamu °et∞zc∙.
OvladaΦ obrßzku je komponenta obsahujφcφ obrßzek (nap°. bitovou mapu).
OvladaΦ obrßzku m∙╛eme pou╛φt k zobrazenφ obrßzku na formulß°i. M∙╛eme
jej takΘ pou╛φt k dr╛enφ skryt²ch obrßzk∙, kterΘ pou╛φvßme v na╣φ aplikaci.
Nap°. m∙╛eme ulo╛it bitovΘ mapy pro ovladaΦe vlastnφho zobrazovßnφ ve skryt²ch
ovladaΦφch obrßzk∙. To provedeme takto: P°idßme komponenty
Image
na formulß°, nastavφme jejich vlastnosti Name, nastavφme jejich
vlastnosti
Visible na false a nastavφme jejich vlastnosti
Picture
na po╛adovanou bitovou mapu pomocφ Editoru obrßzk∙ z Inspektora objekt∙.
Kdy╛ ji╛ mßme obrßzky v aplikaci, m∙╛eme je p°i°adit k °et∞zc∙m v seznamu
°et∞zc∙ (m∙╛eme p°idßvat objekty spoleΦn∞ s °et∞zci nebo je p°i°adit k
ji╛ existujφcφm °et∞zc∙m). Pokud jsou pot°ebnß data dostupnß, pak je vhodnΘ
p°idßvat objekty a °et∞zce najednou. Nßsledujφcφ p°φklad ukazuje jak m∙╛eme
p°idßvat obrßzky k seznamu °et∞zc∙. Je to Φßst aplikace, ve kterΘ spoleΦn∞
s pφsmenem pro ka╛dou existujφcφ jednotku, p°idßme bitovou mapu indikujφcφ
typ jednotky (tato obsluha bude pou╛ita pozd∞ji p°i v²voji sprßvce soubor∙).
void __fastcall TFMForm::FormCreate(TObject
*Sender)
{
int AddedIndex;
char DriveName[4] = "A:\";
for (char Drive = 'A'; Drive <=
'Z'; Drive++)
{
DriveName[0] = Drive;
switch (GetDriveType(DriveName))
{
case DRIVE_REMOVABLE:
// p°idßnφ prvku seznamu
DriveName[1] = '\0'; // bere pouze pφsmeno
jednotky
AddedIndex = DriveList->Items->AddObject(DriveName,
Floppy->Picture->Graphic);
DriveName[1] = ':' // p°evßdφ
zp∞t na tvar A:\
break;
case DRIVE_FIXED:
// p°idßnφ prvku seznamu
DriveName[1] = '\0';
AddedIndex = DriveList->Items->AddObject(DriveName,
Fixed->Picture->Graphic);
DriveName[1] = ':'
break;
case DRIVE_REMOTE:
// p°idßnφ prvku seznamu
DriveName[1] = '\0';
AddedIndex = DriveList->Items->AddObject(DriveName,
Network->Picture->Graphic);
DriveName[1] = ':'
break;
}
if ((int)(Drive - 'A')
== getdisk()) // aktußlnφ jednotka?
DriveList->ItemIndex
= AddedIndex; // pak vybere prvek seznamu
}
}
Kdy╛ nastavφme styl vlastnφho zobrazovßnφ, pak ji╛ Windows nezobrazuje
ovladaΦ na obrazovku. Pro ka╛d² viditeln² prvek v ovladaΦi zaΦne generovat
udßlosti. Na╣e aplikace tyto udßlosti musφ vyu╛φt pro zobrazenφ prvk∙.
D°φve ne╛ aplikace m∙╛e zaΦφt se zobrazovßnφm prvku u stylu Variable,
Windows generuje udßlost OnMeasureItem. Tato udßlost °φkß aplikaci,
kde prvek bude na ovladaΦi zobrazen. Windows urΦuje velikost prvku (velikost
pot°ebnou k zobrazenφ textu prvku souΦasn²m pφsmem). Na╣e aplikace m∙╛e
udßlost zpracovat a zm∞nit volbu Windows. Nap°. chceme-li text prvku nahradit
obrßzkem, pak zadßme velikost obrßzku. Ke zm∞n∞ velikosti prvku vytvo°φme
obsluhu udßlosti OnMeasureItem (komponenty m°φ╛ky tuto udßlost nemajφ).
Tato obsluha udßlosti mß dva d∙le╛itΘ parametry: index prvku a velikost
prvku. Velikost je p°edßvßna odkazem a aplikace ji m∙╛e zmen╣it nebo zv∞t╣it.
Pozice nßsledujφcφho prvku zßvisφ na velikosti p°edchozφch prvk∙. Nap°.
kdy╛ v okn∞ seznamu, aplikace nastavφ v²╣ku prvnφho prvku na 5 bod∙, pak
druh² prvek zaΦne ╣est²m bodem od hornφho okraje ovladaΦe, atd. V komponentßch
ComboBox
a
ListBox m∙╛e aplikace ovliv≥ovat pouze v²╣ku prvku. ⌐φ°ka prvku je
v╛dy ╣φ°ka ovladaΦe. U m°φ╛ek nelze m∞nit velikost bun∞k. Velikost ka╛dΘho
°ßdku a sloupce musφme nastavit p°ed zobrazenφm pomocφ vlastnostφ
ColWidths
a RowHeights.
Nßsledujφcφ k≤d p°ipojen² k obsluze udßlosti OnMeasureItem okna
seznamu urΦuje v²╣ku ka╛dΘho prvku seznamu podle svΘ p°ipojenΘ bitovΘ mapy:
void __fastcall TForm1::ListBox1MeasureItem(TWinControl
*Control,
int Index, int &Height) // v²╣ka je p°edßna odkazem
{
int BitmapHeight=((TBitmap*)ListBox1->Items->Objects[Index])->Height
+ 2;
// ud∞lßme dostateΦnΘ mφsto pro bitovou
mapu (+ 2)
if (BitmapHeight > Height)
Height = BitmapHeight;
}
V p°edchozφm k≤du musφme provΘst p°etypovßnφ vlastnosti Objects
seznamu °et∞zc∙. Tato vlastnost je typu TObject a m∙╛e obsahovat
odkaz na libovoln² typ objektu. Pokud zφskßvßme objekt z pole, musφme provΘst
p°etypovßnφ na aktußlnφ typ prvku.
Kdy╛ aplikace po╛aduje zobrazenφ nebo p°ekreslenφ ovladaΦe, pak Windows
generuje udßlost OnDrawItem (OnDrawCell) pro ka╛d² viditeln²
prvek v ovladaΦi. Tato udßlost obsahuje parametry urΦujφcφ index zobrazovanΘho
prvku, obdΘlnφk, ve kterΘm prvek bude zobrazen a obvykle n∞jakΘ informace
o stavu prvku (nap°. zda prvek mß zaost°enφ). Aplikace zpracuje ka╛dou
udßlost zobrazenφm p°φslu╣nΘho prvku v danΘm obdΘlnφku. Nap°. nßsledujφcφ
k≤d ukazuje jak zobrazit prvky v okn∞ seznamu, kter² mß ke ka╛dΘmu °et∞zci
p°i°azenou bitovou mapu:
void __fastcall TForm1::ListBox1DrawItem(TWinControl
*Control,
int Index, TRect &Rect,
TOwnerDrawState State)
TBitmap *Bitmap = (TBitmap *)ListBox1->Items->Objects[Index];
ListBox1->Canvas->Draw(Rect.Left,
Rect.Top + 2, Bitmap);
ListBox1->Canvas->TextOut(Rect.Left
+ Bitmap->Width + 2, Rect.Top + 2,
ListBox1->Items->Strings[Index]);
}
-
Dßle si ukß╛eme aplikaci zobrazujφcφ seznam pφsem dostupn²ch v systΘmu
(jmΘno pφsma bude v seznamu zobrazeno pomocφ tohoto pφsma; pou╛ijeme seznam
s u╛ivatelsk²m - vlastnφm zobrazovßnφm prvk∙). ZaΦneme novou aplikaci.
Na formulß° umφstφme k hornφmu okraji komponentu Label s textem
Pφsma
systΘmu:, v∞t╣inu plochy formulß°e bude zabφrat komponenta
ListBox
a ve spodnφ Φßsti formulß°e bude dal╣φ komponenta Label (se jmΘnem
vybranΘho pφsma). U komponenty ListBox nastavφme vlastnost
Style
na lbOwnerDrawVariable a vytvo°φme obsluhy zobrazujφcφ seznam. Obsluha
udßlosti OnMeasureItem (udßlost zji╣╗ujφcφ v²╣ku prvku) bude vypadat
takto:
void __fastcall TForm1::ListBox1MeasureItem(TWinControl
*Control,
int Index,
int &Height)
{
ListBox1->Canvas->Font->Name = ListBox1->Items->Strings[Index];
ListBox1->Canvas->Font->Size = 0;
Height = ListBox1->Canvas->TextHeight("Wg")
+2;
}
Obsluha OnDrawItem (zobrazenφ prvku seznamu) vypadß takto:
void __fastcall TForm1::DrawItem(TWinControl
*Control,
int Index,
TRect &Rect, TOwnerDrawState State)
{
ListBox1->Canvas->FillRect(Rect);
ListBox1->Canvas->Font->Name =ListBox1->Items->Strings[Index];
ListBox1->Canvas->Font->Size = 0;
ListBox1->Canvas->TextOut(Rect.Left+1,
Rect.Top+1,
ListBox1->Items->Strings[Index]);
}
Obsluha kliknutφ na prvku seznamu pouze zobrazφ jmΘno vybranΘho prvku
ve spodnφ komponent∞ Label:
Label2->Caption = ListBox1->Items->Strings[ListBox1->ItemIndex];
Zb²vß je╣t∞ vytvo°it obsluhu OnCreate formulß°e. Je tvo°ena
p°φkazem:
ListBox1->Items = Screen->Fonts;
Tφm je aplikace hotova. M∙╛eme ji vyzkou╣et.
-
V tΘto kapitole se je╣t∞ seznßmφme s pou╛φvßnφm dal╣φ ze zßkladnφch komponent
a to s komponentou ScrollBar. P°φmΘ pou╛itφ tΘto komponenty je vzßcnΘ.
Typick²m p°φkladem je umo╛n∞nφ toho, aby si u╛ivatel mohl vybrat celoΦφselnou
hodnotu z urΦitΘho rozsahu. ZaΦneme s v²vojem novΘ aplikace. Na formulß°
umφstφme t°i komponenty ScrollBar a vlevo od ka╛dΘ z nich komponentuLabel.
Ka╛d² posuvnφk se vztahuje k jednΘ ze t°φ zßkladnφch barev a budeme s nimi
urΦovat slo╛ky barvy formulß°e. Posuvnφky majφ mnoho zvlß╣tnφch vlastnostφ.
Min
a Max pou╛φvßme k urΦenφ rozsahu mo╛n²ch hodnot, Position
obsahuje souΦasnou pozici, vlastnosti LargeChange a SmallChange
urΦujφ kroky, o kterΘ se zm∞nφ hodnota posuvnφku. V na╣em p°φklad∞ budou
v╣echny posuvnφky mφt mo╛nΘ hodnoty od 0 do 255, poΦßteΦnφ hodnotu 192
a kroky budou 25 a 1. Obsluha udßlosti OnScroll posuvnφku zm∞nφ
hodnotu Caption sousednφ komponenty Label a barvu formulß°e.
Nap°. pro prvnφ posuvnφk bude tvo°ena p°φkazy:
Label1->Caption = "╚ervenß: " + IntToStr(ScrollPos);
Color=RGB(ScrollBar1->Position,ScrollBar2->Position,ScrollBar3->Position);
Dal╣φ posuvnφky budou pro slo╛ky zelenß a modrß. Jejich obsluhy budou
podobnΘ. Vytvo°te je sami. Funkce RGB vezme t°i hodnoty slo╛ek a vytvo°φ
hodnotu s k≤dem v²slednΘ barvy. Pov╣imn∞te si, ╛e obsluha udßlosti OnScroll
mß t°i parametry: Sender, ScrollCode (druh udßlosti) a ScrollPos
(poslednφ pozici posuvnφku). Druh udßlosti m∙╛e b²t pou╛it pro velice p°esnΘ
rozli╣enφ akcφ u╛ivatele. Jeho hodnota indikuje, zda u╛ivatel posouvß ukazatel
(scTrack, scPosition a scEndScroll), zda kliknul na
╣ipky nebo na li╣tu v jednom ze dvou mo╛n²ch sm∞r∙ (scLineUp,
scLineDown,
scPageUp
a scPageDown) a zda se pokusil o posun mimo rozsah (scTop
a scBottom).
-
Vytvo°te aplikaci, kde na formulß° umφstφte posuvnφk a komponentu Label
s n∞jak²m textem. Pomocφ posuvnφku m∞≥te velikost pφsma komponenty Label
(od 8 do 72).
-
Ta╛enφ m∙╛e usnadnit u╛ivateli manipulaci s objekty na formulß°i. U╛ivatel
m∙╛e tßhnout celΘ komponenty nebo tßhnout prvky z komponenty typu ListBox
do jin²ch komponent.
Ka╛d² ovladaΦ mß vlastnost DragMode, kterß urΦuje jak komponenta
reaguje na zahßjenφ ta╛enφ. Pokud DragMode je dmAutomatic,
pak ta╛enφ zaΦφnß automaticky kdy╛ u╛ivatel stiskne tlaΦφtko my╣i s kurzorem
my╣i nad ovladaΦem. Proto╛e dmAutomatic m∙╛e kolidovat s dal╣φmi
aktivitami my╣i, obvykle nastavujeme DragMode na dmManual
(implicitnφ) a ta╛enφ zahßjφme zpracovßnφm udßlosti stisknutφ tlaΦφtka
my╣i. K zahßjenφ ruΦnφho °φzenφ ta╛enφ volßme metodu BeginDrag komponenty.
BeginDrag p°ebφrß parametr typu bool nazvan² Immediate.
Pokud parametr mß hodnotu true, pak ta╛enφ zaΦφnß bezprost°edn∞,
stejn∞ jako kdy╛ DragMode je nastaveno na dmAutomatic. P°i
hodnot∞ false, ta╛enφ zaΦφnß a╛ p°i nepatrnΘm pohybu my╣φ (tφm lze
rozli╣it zaΦßtek ta╛enφ od kliknutφ). Do obsluhy stisknutφ tlaΦφtka my╣i
m∙╛eme takΘ umφstit n∞jakou podmφnku, nap°. testovat kterΘ tlaΦφtko my╣i
bylo stisknuto.
Nßsledujφcφ k≤d nap°. zpracovßvß udßlost stisknutφ my╣i nad oknem seznamu
soubor∙ a ta╛enφ zahßjφme pouze p°i stisku levΘho tlaΦφtka my╣i:
void __fastcall TFMForm::FileListBox1MouseDown(TObject
*Sender,
TMouseButton Button, TShiftState Shift, int X, int Y)
{
if (Button == mbLeft) // pouze p°i stisknutΘm
levΘm tlaΦφtku
{
TFileListBox *pLB = (TFileListBox
*)Sender;
if (pLB->ItemAtPos(Point(X,Y),
true) >= 0) // je zde prvek?
pLB->BeginDrag(false);
// pokud ano, tßhneme
}
}
D°φve ne╛ m∙╛eme prvek tßhnout, musφme urΦit, kam m∙╛eme prvek p°etßhnout.
Kdy╛ u╛ivatel tßhne cokoliv nad ovladaΦem, pak ovladaΦ zφskß udßlost OnDragOver
a musφme indikovat, zda ovladaΦ m∙╛e ta╛en² prvek akceptovat. C++ Builder
m∞nφ kurzor my╣i v zßvislosti na tom, zda ta╛en² prvek je akceptovateln².
K akceptovßnφ prvku ta╛enΘho nad ovladaΦem vytvo°φme obsluhu udßlostφ OnDragOver
ovladaΦe. Obsluha mß parametr Accept, kter² nastavφme na true,
pokud prvek je akceptovßn. Nastavenφm Accept na true specifikujeme,
╛e pokud v tomto mφst∞ u╛ivatel uvolnφ tlaΦφtko my╣i, pak aplikace m∙╛e
generovat udßlost OnDragDrop pro stejn² ovladaΦ. Pokud Accept
je false, pak aplikace nem∙╛e ukonΦit ta╛enφ prvku nad tφmto ovladaΦem.
To znamenß, ╛e ovladaΦ nikdy nebude generovat udßlost OnDragDrop
pro tento ovladaΦ a nemusφ tedy v∞d∞t, jak ji obslou╛it.
Udßlost OnDragOver mß n∞kolik parametr∙, vΦetn∞ zdroje ta╛enφ
a sou°adnic ukazatele my╣i. Obsluha udßlosti tyto parametry m∙╛e pou╛φt
k urΦenφ, zda ta╛enφ akceptovat. ╚asto ovladaΦ akceptuje ta╛enφ prvku na
zßklad∞ typu zdroje ta╛enφ, ale m∙╛e takΘ akceptovat prvky pouze specifick²ch
instancφ.
V nßsledujφcφm p°φklad∞ adresß°ov² strom akceptuje ta╛enΘ prvky pouze
pokud pochßzejφ z okna seznamu soubor∙:
void __fastcall TForm1::TreeView1DragOver(TObject
*Sender,
TObject *Source, int X, int Y, TDragState
State, bool &Accept)
{
if (Source->InheritsFrom(__classid(TFileListBox)))
Accept = true;
}
NestaΦφ pouze indikovat akceptovßnφ ta╛enφ, ale musφme takΘ definovat
zpracovßnφ p°eta╛enΘho prvku. Pro zpracovßnφ p°eta╛enΘho prvku p°ipojφme
k ovladaΦi akceptujφcφmu ta╛en² prvek obsluhu udßlosti OnDragDrop.
Podobn∞ jako udßlost OnDragOver i udßlost OnDragDrop indikuje
zdroj ta╛enφ a sou°adnice uvoln∞nφ kurzoru my╣i na akceptujφcφm ovladaΦi.
Tyto informace umo╛≥ujφ obsluze zφskat pot°ebnΘ informace od zdroje ta╛enφ
a urΦit, jak ta╛enφ zpracovat. Nap°. adresß°ov² strom akceptujφcφ prvek
ta╛enφ z okna seznamu soubor∙ m∙╛e p°esunout soubor z jeho souΦasnΘho mφsta
do urΦenΘho adresß°e:
void __fastcall TForm1::TreeView1DragDrop(TObject
*Sender,
TObject *Source, int X, int Y)
{
if (Source->InheritsFrom(__classid(TFileListBox)))
{
TTreeNode *pNode = TreeView1->GetNodeAt(X,Y);
// pNode je cφl ta╛enφ
AnsiString NewFile = pNode->Text
+ AnsiString("\") +
ExtractFileName(FileList->FileName);
// jmΘno cφle ta╛enφ
MoveFileEx(FileList->FileName.c_str(),
NewFile.c_str(),
MOVEFILE_REPLACE_EXISTING
| MOVEFILE_COPY_ALLOWED);
}
}
Kdy╛ operace ta╛enφ konΦφ (u╛ivatel p°etßhne prvek nebo uvolnφ tlaΦφtko
my╣i nad ovladaΦem neakceptujφcφm ta╛enφ), pak je zaslßna udßlost OnEndDrag
zp∞t ovladaΦi odkud zaΦalo ta╛enφ. Tato udßlost mß d∙le╛it² parametr nazvan²
Target,
kter² indikuje ovladaΦ akceptujφcφ ta╛enφ. Mß-li tento parametr hodnotu
NULL, pak ta╛enφ neakceptoval ╛ßdn² ovladaΦ. Parametry udßlosti
OnEndDrag
takΘ obsahujφ sou°adnice na p°ijφmajφcφm ovladaΦi, kde ta╛enφ skonΦilo.
V nßsledujφcφm p°φkladu, okno seznamu soubor∙ zpracovßvß udßlost ukonΦenφ
ta╛enφ p°ekreslenφm svΘho seznamu soubor∙, nebo╗ p°eta╛enφm souboru se
obsah seznamu zm∞nil:
void __fastcall TFMForm::FileList1EndDrag(TObject
*Sender,
TObject *Target, int X, int Y)
{
if (Target)
FileList1->Update();
}
-
M∙╛eme pou╛φt TDragObject k p°izp∙sobenφ chovßnφ na╣eho objektu
ta╛enφ. Implicitn∞, udßlosti OnDragOver a OnDragDrop indikujφ
zdroj ta╛enΘho prvku a sou°adnice kurzoru my╣i nad akceptujφcφm ovladaΦem.
M∙╛eme zφskat dal╣φ stavovΘ informace odvozenφm objektu ta╛enφ od TDragObject
a p°edefinovßnφm jeho virtußlnφch metod. Pomocφ TDragObject, zdroj
ta╛enφ je samotn² objekt a ne objekt ovladaΦe jako u objektu TDragControl.
Vytvo°φme u╛ivatelsk² objekt ta╛enφ v udßlosti OnStartDrag.
Pou╛ijeme ve°ejnou funkci IsDragObject v udßlosti OnDragOver
kdy╛ akceptujeme ta╛enφ.
TDragObject umo╛≥uje flexibiln∞j╣φ zpracovßnφ ta╛enφ. Normßln∞
parametr Source udßlostφ OnDragOver a OnDragDrop je
ovladaΦ, kde operace ta╛enφ zaΦala. Pokud vφce ovladaΦ∙ r∙zn²ch typ∙ m∙╛e
b²t zdrojem ta╛enφ stejnΘho typu dat, pak zdroj musφ mφt podporu pro ka╛d²
typ ovladaΦe. Ta╛en² objekt umo╛≥uje cφli znßt pouze jak zpracovat ta╛en²
objekt jako zdroj, nebo╗ ka╛d² ovladaΦ zdroje m∙╛e vytvo°it vhodn² typ
ta╛enΘho objektu ve svΘ udßlosti OnStartDrag. Udßlosti OnDragOver
a OnDragDrop mohou °φci zda zdroj je ta╛en² objekt a zabrßniti ovladaΦi
ve volßnφ IsDragObject.
-
M∙╛eme takΘ zm∞nit tvar ukazatele my╣i v pr∙b∞hu operace ta╛enφ. Provedeme
to nastavenφm vlastnosti DragCursor komponenty. M∙╛eme takΘ vytvo°it
sv∙j zdroj kurzoru.
-
Ka╛d² Windowsovsk² program pou╛φvß zdroje. Zdroje jsou prvky
programu, kterΘ nejsou spustiteln²m k≤dem. Zdroje nap°. zahrnujφ bitovΘ
mapy, kurzory, dialogovß okna, ikony, nabφdky apod. Zdroje jsou obecn∞
obsa╛eny v souborech skriptu zdroj∙ (textov² soubor s p°φponou RC), kterΘ
jsou p°eklßdßny p°ekladaΦem zdroj∙ a potom b∞hem fßze sestavovßnφ jsou
p°ipojeny k aplikaΦnφmu EXE souboru.
Zdroje jsou obvykle spojeny s provediteln²m souborem.
N∞kterΘ zdroje, jako jsou bitovΘ mapy, tabulky °et∞zc∙ a zvukovΘ soubory
mohou b²t ulo╛eny v externφch souborech (BMP, TXT a WAV) nebo mohou b²t
p°ipojeny k aplikaΦnφmu EXE souboru. Umφst∞nφ zdroj∙ do EXE souboru mß
dv∞ v²hody:
-
Zdroje mohou b²t rychle zp°φstup≥ovßny (nenφ zapot°ebφ hledat
jejich umφst∞nφ, staΦφ je zavΘst ze souboru).
-
K≤d a zdroje jsou umφst∞ny v jednΘ jednotce (EXE souboru)
a nejsou zapot°ebφ dal╣φ soubory.
Nev²hodou je zv∞t╣enφ EXE souboru. Tento soubor nenφ v∞t╣φ
ne╛ spojenφ k≤du a externφch zdrojov²ch soubor∙, ale je zapot°ebφ del╣φ
Φas k zavedenφ programu.
Je zapot°ebφ se rozhodnout, zda zdroje budeme dr╛et v
externφch souborech nebo zda je p°ipojφme k EXE souboru. M∙╛eme pou╛φt
oba zp∙soby a dokonce jejich kombinaci v rßmci jednoho programu. TradiΦnφ
Windowsovsk² program obsahuje alespo≥ jedno dialogovΘ okno a ikonu. Aplikace
C++ Builderu se nepatrn∞ li╣φ. Dialogovß okna v C++ Builderu nejsou zdroji
(popis formulß°e je ulo╛en jako zdroj, ale nejednß se o zdroj dialogovΘho
okna). Aplikace C++ Builderu mß tradiΦnφ zdroj ikony. Kdy╛ vytvß°φme aplikaci,
pak C++ Builder p°ebφrß soubor zdroje ikony. Podobn∞, kdy╛ volφme bitovou
mapu pro tlaΦφtko nebo komponentu Image, pak C++ Builder vklßdß
soubor bitovΘ mapy jako Φßst zdroje formulß°e. Formulß° a v╣echny jeho
zdroje jsou spojeny s programov²m souborem p°i p°ekladu a sestavovßnφ programu.
Toto probφhß automaticky.
Jsou ale situace, kdy pot°ebujeme implementovat zdroje
mimo normßlnφ zpracovßnφ C++ Builderu, Nap°. animaci chceme provßd∞t st°φdßnφm
°ady bitov²ch map, kterΘ budou zavßd∞ny jako °ada zdroj∙ (zv²╣enφ rychlosti
provßd∞nφ). Je tedy vhodnΘ znßt, jak C++ Builder p°ipojuje zdroje k programovΘmu
souboru.
Zdroje musφme takΘ vytvo°it. Pokud pou╛φvßme dobr² editor
zdroj∙, pak to nenφ slo╛itΘ. Pro vytvo°enφ bitov²ch map, ikon a kurzor∙
lze pou╛φt Editor obrßzk∙ C++ Builderu. Tφmto editorem ale nenφ mo╛no vytvß°et
jinΘ zdroje. Pokud mßme p°ekladaΦ Borland C++, pak k editaci zdroj∙ m∙╛eme
pou╛φt Resource Workshop z tohoto produktu. Po vytvo°enφ zdroj∙ mßme soubor
RC, kter² m∙╛eme p°idat k projektu C++ Builderu p°φmo nebo jej p°elo╛it
do tvaru RES pomocφ p°ekladaΦe zdroj∙ (BRCC32.EXE) a k projektu p°idat
soubor p°elo╛en²ch zdroj∙.
Soubory RES nebo RC p°idßvßme k projektu pomocφ sprßvce
projektu. Sprßvce projektu zobrazφme volbou View | Project Manager.
Zde stiskneme tlaΦφtko Add File To Project na palet∞ nßstroj∙ sprßvce
a v dialogovΘm okn∞ otev°enφ souboru vybereme p°idßvan² soubor zdroj∙ (se
Sprßvcem projekt∙ se podrobn∞ji seznßmφme pozd∞ji).
-
Pou╛itφ zdroj∙ si ukß╛eme na jednoduchΘ aplikaci. Tentokrßt pou╛ijeme ji╛
hotovou aplikaci Jumping Jack. Tento program ukazuje jednoduchou
animaci se zvukov²m efektem. Hlavnφ formulß° obsahuje dv∞ tlaΦφtka, komponentu
Image
a komponentu Label. V tΘto aplikaci si ukß╛eme jak zavßd∞t bitovou
mapu ulo╛enou jako zdroj, jak zavßd∞t a zobrazovat zdroje °et∞zc∙ a jak
p°ehrßvat zvukovΘ soubory ulo╛enΘ jako zdroje. Aplikaci
si stßhn∞te a vyzkou╣ejte.
Podφvejte se na ΦervenΘ °ßdky v nßsledujφcφm v²pisu hlaviΦkovΘho souboru
aplikace.
#ifndef JJMainH
#define JJMainH
#include <vcl\Classes.hpp>
#include <vcl\Controls.hpp>
#include <vcl\StdCtrls.hpp>
#include <vcl\Forms.hpp>
#include <vcl\ExtCtrls.hpp>
class TMainForm : public TForm
{
__published: // IDE-managed
Components
TButton *Start;
TButton *Stop;
TImage *Image;
TLabel *Label;
void __fastcall FormCreate(TObject
*Sender);
void __fastcall StartClick(TObject
*Sender);
void __fastcall StopClick(TObject
*Sender);
private:
// User declarations
bool done;
void DrawImage(String&
name);
public:
// User declarations
virtual __fastcall TMainForm(TComponent*
Owner);
};
extern PACKAGE TMainForm *MainForm;
#endif
Na prvnφm z nich deklarujeme datovou slo╛ku typu bool, kterß
je pou╛ita k urΦenφ zda animaci zastavit. Na druhΘm °ßdku je deklarace
metody pou╛itΘ k zobrazovßnφ bitovΘ mapy v komponent∞ Image.
Ve v²pisu zdrojovΘho k≤du jednotky, si pov╣imn∞te dvou funkcφ API,
kterΘ jsou pou╛ity k zavßd∞nφ zdroj∙ °et∞zc∙ a zvukov²ch soubor∙. Na ΦervenΘm
°ßdku, funkce LoadString zavßdφ zdroj °et∞zce do textovΘ vyrovnßvacφ
pam∞ti na zßklad∞ ΦφselnΘ identifikace °et∞zce. ╪et∞zec je potom p°i°azen
vlastnosti Caption komponenty Label. Na modrΘm °ßdku, funkce
PlaySound
je pou╛ita k p°ehrßnφ zdroje zvukovΘho souboru. P°φznak SND_ASYNC urΦuje,
╛e zvuk bude p°ehrßvßn asynchronn∞, tj. animace bude probφhat souΦasn∞
s p°ehrßvßnφm. P°φznak SND_RESOURCE °φkß Windows, ╛e zvuk je obsa╛en ve
zdroji a ne v souboru na disku. Ob∞ tyto funkce p°ebφrajφ globßlnφ prom∞nnou
HInstance,
kterß °φkß Windows, kde hledat zdroje ve spustitelnΘm souboru. Pokud poΦφtaΦ
nenφ vybaven zvukovou kartou, pak zvuk neusly╣φme.
#include <vcl\vcl.h>
// zapot°ebφ pro funkci PlaySound()
#include <vcl\mmsystem.hpp>
#pragma hdrstop
#include "JJMain.h"
#pragma package(smart_init)
#pragma resource "*.dfm"
// definice pro zdroje °et∞zc∙
#define IDS_UP 101
#define IDS_DOWN 102
HINSTANCE hInst;
TMainForm *MainForm;
//--------------------------------------------------------------
__fastcall TMainForm::TMainForm(TComponent*
Owner)
: TForm(Owner), done(false)
{
}
void __fastcall TMainForm::FormCreate(TObject
*Sender)
{
hInst = (HINSTANCE)HInstance;
// Zavedenφ a zobrazenφ prvnφ bitovΘ
mapy
Image->Picture->Bitmap->
LoadFromResourceName((int)hInst,
"ID_BITMAP1");
}
void __fastcall TMainForm::StartClick(TObject
*Sender)
{
String s = "ID_BITMAP";
char buff[10];
done = false;
while (!done) {
for (int i=1;i<6;i++)
{
String resName
= s + String(i);
DrawImage(resName);
}
LoadString(hInst, IDS_UP,
buff, sizeof(buff));
Label->Caption = buff;
Label->Refresh();
PlaySound("ID_WAVEUP",
hInst, SND_ASYNC | SND_RESOURCE);
Sleep(200);
for (int i=5;i>0;i--)
{
String resName
= s + String(i);
DrawImage(resName);
}
PlaySound("ID_WAVEDOWN",
hInst, SND_ASYNC | SND_RESOURCE);
LoadString(hInst, IDS_DOWN,
buff, sizeof(buff));
Label->Caption = buff;
Label->Refresh();
Sleep(200);
}
}
void __fastcall TMainForm::StopClick(TObject
*Sender)
{
done = true;
}
void TMainForm::DrawImage(String& name)
{
Image->Picture->Bitmap->LoadFromResourceName((int)hInst,
name);
Application->ProcessMessages();
Sleep(20);
}
Nßsleduje v²pis zaΦßtku souboru skriptu zdroj∙.
#define IDS_UP 101
#define IDS_DOWN 102
STRINGTABLE
{
IDS_UP, "Up"
IDS_DOWN, "Down"
}
ID_WAVEUP WAVE "up.wav"
ID_WAVEDOWN WAVE "down.wav"
ID_BITMAP1 BITMAP LOADONCALL MOVEABLE DISCARDABLE
IMPURE
{
'42 4D 76 02 00 00 00 00 00 00 76 00
00 00 28 00'
'00 00 20 00 00 00 20 00 00 00 01 00
04 00 00 00'
...
╚erven∞ oznaΦenΘ °ßdky definujφ zdroj tabulky °et∞zc∙. Tabulku °et∞zc∙
snadno vytvo°φme v libovolnΘm textovΘm editoru. «lutΘ °ßdky jsou zdroje
WAVE (pro oba soubory WAV, kterΘ byly p°edem zaznamenßny a umφst∞ny do
adresß°e projektu). Kdy╛ p°ekladaΦ zdroj∙ uvidφ deklaraci WAVE, p°eΦte
urΦen² soubor a p°elo╛φ jej do binßrnφho souboru zdroj∙. BitovΘ mapy jsou
vytvo°eny v tradiΦnφm editoru zdroj∙. Popis zdroj∙ pro bitovΘ mapy m∙╛e
b²t velmi dlouh². Zbytek na╣eho souboru jsou zdroje bitov²ch map.