|
Otßzky a odpov∞di |
|||||
Programßtorskß poradna |
||||||
╚asovß nßroΦnost (min): |
ZaΦßteΦnφk |
PokroΦil² |
Profesionßl |
|||
|
|
|
||||
|
Pou₧it² operaΦnφ systΘm : Hlavnφ v²vojov²
nßstroj : DalÜφ v²vojov² software : Jin² software : |
Windows 2000 SP3 Visual C# .NET 2002 Visual C++ .NET 2002 Äßdn² |
||||
|
|
Dobr² den, cht∞l bych vßs po₧ßdat o pomoc p°i °eÜenφ svΘho problΘmu. Pot°eboval
bych z t°φdy, kterou mßm p°ipravenou v °φzenΘm C++, odvodit
podt°φdu v C# a z konstruktoru tΘto podt°φdy zavolat metodu bßzovΘ t°φdy.
M∙₧ete mi, prosφm, poradit? |
Poradit vßm samoz°ejm∞ m∙₧u a takΘ to ihned
ud∞lßm. P°edpoklßdejme, ₧e k≤d t°φdy v °φzenΘm C++ vypadß nßsledovn∞:
//Tento
programov² k≤d se nachßzφ v hlaviΦkovΘm souboru (.h) //°φzenΘ
t°φdy. #pragma once //Import
metadat z assembly System.Windows.Forms.dll. #using
<System.Windows.Forms.dll> //Import
jmenn²ch prostor∙. using namespace System; using namespace System::Windows::Forms; //Deklarace
jmennΘho prostoru t°φdy. namespace RizeneCPP { áááááá //DeklaraΦnφ
p°φkaz °φzenΘ t°φdy s nßzvem TridaCPP. áááááá public __gc class TridaCPP áááááá { áááááááááááá //Ve°ejn∞
p°φstupn² konstruktor t°φdy. áááááááááááá public:
TridaCPP() áááááááááááááááááááááááááá { áááááááááááááááááááááááááááááááááááááááááááááá áááááááááááááááááááááááááá } áááááááááááá ááááááááááááááááááá //
Metoda, kterß bude volßna z k≤du jazyka C#. ááááááááááááááááááá void
Metoda(void) áááááááááááááááááááááááááá { ááááááááááááááááááááááááááááááááá //Aktivace metody Show t°φdy MessageBox, kterΘ ááááááááááááááááááááááááááááááááá //je p°edßn °φzen² textov² °et∞zec znak∙. ááááááááááááááááááááááááááááááááá MessageBox::Show(S"Metoda
byla aktivovßna."); áááááááááááááááááááááááááá } áááááá }; } Budete-li chtφt d∞dit z tΘto t°φdy
v C#, m∙₧ete pou₧φt tento k≤d: using System; namespace JmennyProstorCS { áááááá /// <summary> áááááá /// T°φda je podt°φdou t°φdy vytvo°enΘ v °φzenΘm C++. áááááá /// </summary> áááááá áááááá //DeklaraΦnφ
p°φkaz, jen₧ vytvß°φ podt°φdu z t°φdy áááááá //napsanΘ v
°φzenΘm C++. áááááá public class TridaCS :
RizeneCPP.TridaCPP áááááá { áááááááááááá //Konstruktor
t°φdy. áááááááááááá public
TridaCS() áááááááááááá { ááááááááááááááááááá //Pou₧itφ
klφΦovΘho slova base, kterΘ umo₧≥uje volat ááááááááááááááááááá //metody
bßzovΘ t°φdy z odvozen²ch t°φd. ááááááááááááááááááá base.Metoda(); áááááááááááá } áááááá } } Aktivaci metody bßzovΘ t°φdy zabezpeΦuje
klφΦovΘ slovo base, za kter²m nßsleduje teΦka a pojmenovßnφ cφlovΘ
metody, kterou budete chtφt zavolat. Aby t°φda v C# v∞d∞la, od jakΘ t°φdy je
odvozenß, je nutnΘ do projektu s podt°φdou zaΦlenit referenci na
dynamicky linkovanou knihovnu (DLL), v nφ₧ je ulo₧en k≤d °φzenΘ t°φdy
napsanΘ v C++.
Finßlnφm krokem je vytvo°enφ instance
podt°φdy ve zvolenΘm zpracovateli udßlosti (nap°. button1_Click): private void button1_Click(object
sender, System.EventArgs e) áááááá { áááááááááááá JmennyProstorCS.TridaCS Objekt = new JmennyProstorCS.TridaCS(); áááááá } |
|
DoΦetl jsem se, ₧e C# podporuje tzv. boxing, ovÜem nevφm, co
tento termφn znamenß. Cht∞l bych vßs proto poprosit o vysv∞tlenφ a takΘ
programovou ukßzku. D∞kuji p∞kn∞. |
V²raz boxing oznaΦuje techniku
p°etypovßnφ hodnotovΘho datovΘho typu na objektov² prot∞jÜek. Pov∞zme, ₧e
mßme deklarovanou a inicializovanou prom∞nnou x datovΘho typu int: int x = 100; Typ int
je primitivnφm a souΦasn∞ hodnotov²m typem, co₧ znamenß, ₧e je schopen
uchovßvat jenom platnΘ celoΦφselnΘ hodnoty ze stanovenΘho intervalu. Kdy₧
vytvo°φte prom∞nnou typu int, C# vyhradφ v pam∞ti poΦφtaΦe dostatek
mφsta pro ulo₧enφ hodnoty tΘto prom∞nnΘ. Pam∞¥ov² prostor, do n∞ho₧ jsou
uklßdßny hodnoty hodnotov²ch datov²ch typ∙, se naz²vß zßsobnφk (stack).
Zßsobnφk je jednoduchß a znaΦn∞ efektivnφ datovß struktura, kterß pracuje na
principu LIFO (Last-In-First-Out, Poslednφ-Dovnit°-Prvnφ-Ven). Podle tohoto
principu je mo₧nΘ ze zßsobnφku brßt jako prvnφ tu hodnotu, kterß byla na
zßsobnφk umφst∞na jako poslednφ. Na druhΘ stran∞ existujφ referenΦnφ datovΘ
typy. Prom∞nnΘ t∞chto typ∙, na rozdφl od jejich hodnotov²ch koleg∙,
neobsahujφ hodnotu, n²br₧ odkaz, neboli referenci, chcete-li.
Z technickΘho hlediska p°edstavuje odkaz pam∞¥ovou adresu. Mßme-li tedy
odkaz, vφme, ₧e na jistΘ pam∞¥ovΘ adrese se nachßzφ n∞jakß cφlovß entita.
Touto entitou b²vß zpravidla objekt. ReferenΦnφ prom∞nnΘ jsou zajφmavΘ takΘ
z jinΘho d∙vodu: AΦkoliv ony samotnΘ jsou uklßdßny na zßsobnφk, entita,
na nφ₧ ukazujφ, se nachßzφ v jinΘ pam∞¥ovΘ oblasti, kterΘ se °φkß °φzenß
hromada (managed heap). Deklarace a inicializace referenΦnφ prom∞nnΘ m∙₧e mφt
tuto podobu: Form y = this; á Odkazovß
prom∞nnß y m∙₧e obsahovat odkaz na instance (objekty) t°φdy Form.
D∙kazem tohoto tvrzenφ je skuteΦnost, ₧e prom∞nnß y je okam₧it∞
·sp∞Ün∞ inicializovßna pomocφ klφΦovΘho slova this. KlφΦovΘ slovo this
p°edstavuje odkaz na aktußlnφ instanci t°φdy Form. áááá Pam∞¥ovß
nßroΦnost prom∞nn²ch hodnotov²ch typ∙ je pom∞rn∞ nφzkß (n∞kolik bajt∙) a
prßce s nimi na zßsobnφk∙ efektivnφ. V jist²ch p°φpadech by ovÜem
bylo vhodnΘ, kdyby bylo mo₧nΘ s prom∞nnou hodnotovΘho typu pracovat jako
s prom∞nnou referenΦnφho typu. A prßv∞ tuto situaci °eÜφ boxing. Podstata boxingu spoΦφvß v tom,
₧e prom∞nnou hodnotovΘho typu äzaboxujemeô. Tuto operaci m∙₧eme provΘst
pomocφ tohoto programovΘho k≤du: object z = x; Technika boxing probφhß p°ibli₧n∞
v t∞chto krocφch: 1.
Na °φzenΘ hromad∞ je vytvo°en objekt t°φdy System.Object.
2.
Hodnota prom∞nnΘ x je nakopφrovßna do
tohoto objektu. 3.
Je vrßcena pam∞¥ovß adresa, na kterΘ se °φzen²
objekt nachßzφ. 4.
Tato pam∞¥ovß adresa je ulo₧ena do p°ipravenΘ
referenΦnφ prom∞nnΘ z. Ano, tento algoritmus je reßln², i kdy₧
p°iznßvßm, ₧e na prvnφ pohled vßm m∙₧e p°ipadat zvlßÜtnφ. OvÜem, jak je mo₧nΘ
uvedenΘ p°etypovßnφ? JednoduÜe proto, ₧e vÜechny typy, s kter²mi
v rßmci .NET Framework Class Library pracujeme, jsou odvozeny od
zßkladnφho typu System.Object. Je-li tomu tak, pomocφ indukce dojdeme
k poznßnφ, ₧e kdy₧ jsou vÜechny typy odvozenΘ od typu System.Object,
je mo₧nΘ takΘ vÜechny typy zp∞tn∞ p°etypovat na tento bßzov² datov² typ.á Obr. 1 û Grafickß
ilustrace techniky boxing Pro programßtory je k dispozici takΘ
opaΦnß operace k boxingu, tzv. unboxing.
Nakonec dodejme, ₧e s boxingem se
m∙₧ete st°etnou i v jin²ch programovacφch jazycφch platformy .NET, mezi
kterΘ pat°φ Visual Basic .NET Φi C++ s °φzen²mi rozÜφ°en²mi (managed
extensions).
|
|
Cht∞l bych z aplikace napsanΘ v C# zavolat API funkci
Windows, ovÜem nem∙₧u najφt zp∙sob, jak to provΘst. Mohl byste mi poradit? |
Budete-li se pokouÜet volat z °φzenΘ
aplikace ne°φzenou funkci aplikaΦnφho programovacφho rozhranφ (API) Windows,
budete muset splnit p°ed samotn²m pou₧itφm vßmi po₧adovanΘ funkce n∞kolik
podmφnek: 1.
Deklaraci API funkce musφ p°edchßzet pou₧itφ
specißlnφho atributu DllImportAttribute, kter² se nachßzφ ve jmennΘm
prostoru System.Runtime.InteropServices. Atribut DllImportAttribute
naznaΦuje, ₧e bude importovßna API funkce s ne°φzen²m k≤dem. Ve
skuteΦnosti je atribut pouze jin²m oznaΦenφm pro specißlnφ t°φdu se stejn²m
nßzvem (DllImportAttribute). Konstruktor tΘto t°φdy pracuje
s jednφm parametrem typu string, kter²m je nßzev DLL knihovny, ve
kterΘ je ulo₧en k≤d API funkce, kterou chcete pou₧φt. 2.
DeklaraΦnφ p°φkaz API funkce musφ obsahovat
klφΦovß slova static a extern. 3.
Deklarace API funkce v °φzenΘm k≤du musφ
p°esn∞ odpovφdat prototypu funkce v ne°φzenΘm k≤du. To znamenß, ₧e
deklarace musφ obsahovat stejnΘ jmΘno, dßle stejnou signaturu
s p°φsluÜn²mi datov²mi typy formßlnφch parametr∙ funkce a takΘ stejnou
nßvratovou hodnotu (pokud existuje). Jestli₧e budou spln∞ny tyto podmφnky, bude
API funkce ·sp∞Ün∞ naimportovßna do k≤du vaÜφ °φzenΘ aplikace. S API
funkcφ m∙₧ete poslΘze pracovat jako s jakoukoliv jinou funkcφ. Podφvejme
se na ukßzku pou₧itφ API funkce operaΦnφho systΘmu Windows: áááááááááááá // ...
Tento programov² k≤d se nachßzφ uvnit° t°φdy Form1. áááááááááááá static
void Main() áááááááááááá { ááááááááááááááááááá Application.Run(new Form1()); áááááááááááá } áááááááááááá [System.Runtime.InteropServices.DllImport("User32")] ááááááááááááááááááá private
static extern
bool MoveWindow(int
hWnd, ááááááááááááááááááá int
X, int Y, int
nWidth, int nHeight, bool
bRepaint); áááááááááááá [System.Runtime.InteropServices.DllImport("User32")] ááááááááááááááááááá private
static extern
bool AnimateWindow(int
hWnd, ááááááááááááááááááá uint
dwTime, uint dwFlags); áááááááááááá private
void button1_Click(object
sender, System.EventArgs e) áááááááááááá { ááááááááááááááááááá frm = new Form(); ááááááááááááááááááá frm.Load += new EventHandler(frm_Load); ááááááááááááááááááá frm.Show(); áááááááááááá } áááááááááááá áááááááááááá Form frm; áááááááááááá private
void frm_Load(object
sender, System.EventArgs e) áááááááááááá { ááááááááááááááááááá int
handle = frm.Handle.ToInt32(); ááááááááááááááááááá MoveWindow(handle, 362,
234, 300, 300, true); ááááááááááááááááááá AnimateWindow(handle, 200,
0x00080000); áááááááááááá } áááááááááááá // ...
zde pokraΦuje k≤d t°φdy Form1. Ukßzkov² programov² k≤d pou₧φvß pro p°esun
a animaci nov∞ vytvo°enΘ instance t°φdy Form dv∞ API funkce: MoveWindow
a AnimateWindow. P°ed ka₧dou z funkcφ se nachßzφ atribut DllImport
se jmΘnem dynamicky linkovanΘ knihovny (DLL), ve kterΘ je ulo₧en k≤d danΘ funkce
(ob∞ zde pou₧itΘ funkce jsou ulo₧eny v souboru User32.dll). Velmi
d∙le₧itΘ je, aby byl atribut zapsßn v hranat²ch zßvorkßch. Za atributem
se nachßzφ samotn² deklaraΦnφ p°φkaz, kter² je slo₧en z modifikßtoru
p°φstupu (private), klφΦov²ch slov static a extern, typem
nßvratovΘ hodnoty funkce a jejφ signaturou (datovΘ typy p°itom musφ odpovφdat
datov²m typ∙m pou₧itφm v ne°φzenΘm k≤du API funkce). Ve v²Üe uvedenΘ
programovΘ ukßzce je dßle deklarovßna referenΦnφ prom∞nnß frm
s oborem t°φdy, kterΘ m∙₧e uchovßvat referenci na instance t°φdy Form.
áV udßlostnφ procedu°e button1_Click
je vytvo°ena novß instance t°φdy Form,
p°iΦem₧ dochßzφ takΘ k vytvo°enφ systΘmovΘho delegßta (EventHandler) pro zpracovatele udßlosti
Load nov∞ vytvo°enΘ instance.
Jakmile bude aktivovßna metoda Show objektu frm, delegßt
usm∞rnφ program tak, aby byl uskuteΦn∞n programov² k≤d, jen₧ se nachßzφ ve
zpracovateli udßlosti frm_Load. Kdy₧ dojde k udßlosti Load
objektu frm, bude vykonßn k≤d zpracovatele frm_Load (k udßlosti
dojde po zavolßnφ metody Show p°φsluÜnΘ instance). Zpracovatel
udßlosti frm_Load obsahuje nßsledujφcφ °ßdky programovΘho k≤du: private void frm_Load(object
sender, System.EventArgs e) áááááá { áááááááááááá int
handle = frm.Handle.ToInt32(); áááááááááááá MoveWindow(handle, 362, 234, 300,
300, true); áááááááááááá AnimateWindow(handle, 200,
0x00080000); áááááá } Co ve
skuteΦnosti tento k≤d provßdφ? Tak p°edevÜφm, je zφskßn handle okna instance
t°φdy Form. Handle p°edstavuje jednoznaΦn² identifikßtor, pomocφ
kterΘho Windows p°istupujφ k vytvo°enΘ instanci (hodnota identifikßtoru
handle je v tomto p°φpad∞ p°evedena do podoby 32bitovΘho celΘho Φφsla
pomocφ metody ToInt32). Handle okna pot°ebujeme zφskat, nebo¥ jej
vyu₧ijeme v obou API funkcφch. Abyste p°esn∞ v∞d∞li, co uvedenΘ API
funkce provßd∞jφ, p°edstavφme si je podrobn∞ji: 1.
API funkce
MoveWindow mß tuto vÜeobecnφ podobu (v C/C++): BOOL MoveWindow( á HWND hWnd,ááááá // handle okna á int X,ááááááááá // horizontßlnφ
pozice okna
á int Y,ááááááááá // vertikßlnφ
pozice okna á int nWidth,áááá //
Üφ°ka okna
á int nHeight,ááá // v²Üka
okna á BOOL bRepaintáá // volba, kterß
urΦuje, zdali bude po p°emφst∞nφ realizovßno áááááááááááááááááááááááááááááááááá ááááááááááááááááá // takΘ
p°ekreslenφ okna ); Podoba naÜφ funkce je nßsledovnφ: MoveWindow(handle,
362, 234, 300, 300, true); Funkce zachovßvß implicitnφ velikost okna instance t°φdy Form
(300x300 pixel∙), ovÜem m∞nφ pozici levΘho hornφho bodu okna na bod se
sou°adnicemi (362, 234). Poslednφ parametr (bRepaint) je nastaven na
hodnotu true, co₧ znamenß, ₧e ihned potΘ, co se okno instance p°esune,
bude provedeno jeho p°ekreslenφ. á áá 2.
API funkce
AnimateWindow mß tuto vÜeobecnφ
podobu (op∞t v C/C++): BOOL AnimateWindow( á HWND
hwnd,áááá // handle okna á DWORD
dwTime,á // doba
trvßnφ animace okna á DWORD
dwFlagsá // typ
animace ); A op∞t se podφvejme na naÜφ implementaci funkce AnimateWindow: AnimateWindow(handle,
200, 0x00080000); Prvnφm
parametrem funkce je handle okna, kterΘ bude animovßno. Druh² parametr (dwTime)
je datovΘho typu DWORD (typ DWORD p°edstavuje 32bitovΘ celΘ
Φφslo bez znamΘnka, jeho₧ maximßlnφ hodnota je 232-1). V C# se typ DWORD
samoz°ejm∞ nepou₧φvß, ovÜem jeho ekvivalentem je datov² typ uint, jen₧
disponuje stejn²m rozsahem platn²ch celoΦφseln²ch hodnot. Parametr dwTime
odpovφdß dob∞ trvßnφ animace, kterß se udßvß v milisekundßch.
V naÜem p°φpad∞ bude animace trvat 200 milisekund, co₧ je doporuΦenß
hodnota danß zp∙sobem prßce operaΦnφho systΘmu. Nejhroziv∞ji pravd∞podobn∞
vypadß t°etφ parametr (dwFlags), jeho₧ hodnotou je podivn∞ vyhlφ₧ejφcφ
Φφslo v ÜestnßctkovΘ soustav∞ 0x0008000. Numerickß hodnota 0x0008000
odpovφdß internφ konstant∞ AW_BLEND,
kterß se pou₧φvß v p°φpad∞, kdy mß b²t okno animovßno pomocφ tzv. fade
efektu. Fade efekt znamenß plynulΘ animovßnφ zobrazenφ okna, p°iΦem₧ na
zaΦßtku je okno tak°ka pr∙hlednΘ a postupn∞ se äzapl≥ujeô do standardnφho
barevnΘho schΘmatu a podoby. á
|
|
Doposud jsem programoval ve Visual Basicu .NET. Myslφte, ₧e bych se
mohl nauΦit programovat takΘ ve Visual C#? |
Zcela jist∞ ano. Visual C# je velmi
zajφmav² jazyk, kter² vhodn∞ kombinuje rychl² nßvrh aplikacφ, jen₧ je znßm²
prßv∞ z Visual Basicu a flexibilnφ syntaxi, kterß je p°ednostφ jazyka
C++. Proto₧e vÜechny jazyky platformy .NET vyu₧φvajφ spoleΦnΘ integrovanΘ
prost°edφ, na prvnφ pohled mo₧nß ani nepost°ehnete, ₧e se nachßzφte uvnit°
Visual C#. Visual C# taktΘ₧ nabφzφ vizußlnφ v²voj aplikacφ, tak₧e grafickou
podobu aplikace m∙₧ete navrhnout p°esn∞ tak, jak to d∞lßte ve Visual Basicu
.NET. Na druhΘ stran∞ je pravdou, ₧e zßpis programovΘho k≤du se od Visual
Basicu podstatn∞ liÜφ a zde vßm zcela urΦit∞ pom∙₧e p°edchßzejφcφ zkuÜenost
s jazykem C nebo C++ (p°φpadn∞ s Javou). Pokud neznßte uvedenΘ
jazyky, nemusφte zoufat. Serißl ZaΦφnßme
s jazykem Visual C# vßm poskytne vÜechny pot°ebnΘ informace nato,
abyste mohli psßt svΘ prvnφ programy i ve Visual C#. Ve skuteΦnosti jsou
jazyky Visual C# a Visual Basic .NET do velkΘ mφry podobnΘ ve smyslu implementace
stejn²ch, nebo p°inejmenÜφm velmi podobn²ch programovacφch prvk∙. Ku
p°φkladu, oba jazyky umo₧≥ujφ °φdit tok programu pomocφ rozhodovacφ
konstrukce If (if
v C#), ovÜem zßpis tΘto konstrukce je v C# jin² ne₧ ve Visual Basicu (podobn∞
je tomu takΘ t°eba p°i cyklech Φi prvcφch OOP). SeΦteno a podtr₧eno, jestli₧e
dob°e ovlßdßte Visual Basic .NET, p°i pilnΘm studiu se do taj∙ Visual C# m∙₧ete
dostat velmi rychle. Pon∞kud problematiΦt∞jÜφ je ovÜem p°echod k Visual
C# pro programßtory, kte°φ pracujφ s Visual Basicem verze 6. Ty toti₧
budou muset nejd°φve zvlßdnout vÜechny inovace a modifikace, je₧ p°inßÜφ
v²vojovß platforma .NET.áá ááááááááá |
|
Pracuji s formulß°em, kter² bych pot°eboval vertikßln∞ i
horizontßln∞ vycentrovat na obrazovce poΦφtaΦe. Vφm, ₧e v re₧imu nßvrhu
mohu nastavit vlastnost StartPosition na hodnotu CenterScreen,
co mßm vÜak ud∞lat, kdy₧ chci provΘst vyst°ed∞nφ formulß°e za b∞hu programu? |
Udßlostnφ proceduru Load formulß°e upravte do nφ₧e uvedenΘ podoby: áááááá private
void Form1_Load(object
sender, System.EventArgs e) áááááááááááá { ááááááááááááááááááá this.Top
= (Screen.PrimaryScreen.Bounds.Height - this.Height)
/ 2; ááááááááááááááááááá this.Left
= (Screen.PrimaryScreen.Bounds.Width - this.Width)
/ 2; áááááááááááá } Abyste mohli provΘst vyst°ed∞nφ formulß°e,
musφte znßt rozm∞ry zobrazovacφ plochy obrazovky a rozm∞ry samotnΘho
formulß°e. Rozm∞ry formulß°e jsou znßmΘ, nakolik Visual C# implicitn∞ vytvß°φ
formulß°e s velikostφ 300x300 obrazov²ch bod∙ neboli pixel∙. P°i zrozenφ
instance formulß°e jsou do vlastnostφ Height a Width tΘto
instance ulo₧eny hodnoty 300 pixel∙. Pro zjiÜt∞nφ rozm∞r∙ viditelnΘ plochy
obrazovky pou₧ijeme t°φdu Screen. Konstruktor t°φdy Screen ovÜem
nenφ ve°ejn² a proto nenφ mo₧nΘ p°φmo vytvß°et instance tΘto t°φdy. Pokud
ovÜem zavolßme statickou vlastnost PrimaryScreen, poda°φ se nßm zφskat
instanci t°φdy Screen. Vrßcenß
instance p°edstavuje hlavnφ zobrazovacφ jednotku poΦφtaΦovΘho systΘmu (pokud
systΘm pracuje jenom s jednou obrazovkou, bude vrßcena tato,
v opaΦnΘm p°φpad∞ bude vrßcena ta zobrazovacφ jednotka, kterß je nakonfigurovßna
jako primßrnφ). Dßle pokraΦujeme zavolßnφm vlastnosti Bounds vytvo°enΘ
instance t°φdy Screen. Vlastnost Bounds vracφ instanci t°φdy Rectangle
(jde o objekt, jen₧ popisuje obdΘlnφkov² region hlavnφ zobrazovacφ jednotky).
Mßme-li instanci t°φdy Rectangle, m∙₧eme koneΦn∞ pou₧φt vlastnost Height
(resp. Width) pro zjiÜt∞nφ v²Üky (resp. Üφ°ky) viditelnΘ plochy
obrazovky. P°edpoklßdejme, ₧e vlastnφte 17-palcov² monitor a pou₧φvßte
rozliÜenφ 1024x768 obrazov²ch bod∙. Za t∞chto podmφnek vrßtφ p°φkaz Screen.PrimaryScreen.Bounds.Height
hodnotu 768 a p°φkaz Screen.PrimaryScreen.Bounds.Width zase vrßtφ hodnotu
1024. Od takto zφskan²ch hodnot poslΘze odeΦteme hodnoty, kterΘ reprezentujφ v²Üku
(resp. Üφ°ku) formulß°e a finßlnφ v²sledky vyd∞lφme dv∞ma. Do vlastnosti Top
formulß°e bude po provedenφ vÜech nastφn∞n²ch operacφ ulo₧ena hodnota 234,
zatφmco vlastnost Left bude obsahovat hodnotu 362 (viz obrßzek). ááááá |
|
Cht∞l bych se zeptat, jak je mo₧nΘ ve Visual C# vytvß°et zpracovatele
udßlosti, a to jak v re₧imu nßvrhu, tak i za b∞hu aplikace.á |
V re₧imu nßvrhu aplikace vytvo°φte
zpracovatele udßlosti takto: 1.
Na formulß°i vyberte ten ovlßdacφ prvek, pro
kter² chcete vytvo°it zpracovatele udßlosti. 2.
V okn∞ Properties Window klepn∞te na
tlaΦφtko Events (). 3.
Vyhledejte polo₧ku s nßzvem po₧adovanΘ
udßlosti (nap°. Click) a poklepejte na tuto polo₧ku. 4.
Visual C# okam₧it∞ vygeneruje programovou kostru
udßlostnφ procedury a otev°e okno editoru pro zßpis programovΘho k≤du. 5.
Vypl≥te t∞lo vytvo°enΘ udßlostnφ procedury vhodn²m
programov²m k≤dem. Jestli₧e budete chtφt spojit udßlost
s jejφm zpracovatelem za b∞hu programu, budete muset vÜechny pot°ebnΘ
operace provΘst p°φmo z programovΘho k≤du. Aby bylo mo₧nΘ vytvo°it
spojenφ mezi udßlostφ a p°φsluÜn²m zpracovatelem, musφte vytvo°it systΘmovΘho
delegßta, kter² bude zodpov∞dn² za to, aby udßlost naÜla svΘho zpracovatele. Nßsledujφcφ fragment k≤du byl vy≥at ze
t°φdy Form1. M∙₧ete si v n∞m vÜimnout udßlostnφ proceduru button1_Click.
V tΘto procedu°e dochßzφ k vytvo°enφ novΘ instance t°φdy Button (s nßzvem btnTlaΦφtko1), dßle
jsou nastaveny n∞kterΘ klφΦovΘ vlastnosti nov∞ vytvo°enΘ instance a instance
je p°idßna do kolekce ovlßdacφch prvk∙ formulß°e. Spojenφ mezi udßlosti Click tlaΦφtka
btnTlaΦφtko1 a zpracovatelem tΘto udßlosti (btnTlaΦφtko1_Click)
zabezpeΦuje systΘmov² delegßt EventHandler. P°i tΘto programovΘ
operaci je velmi d∙le₧itΘ sprßvnΘ pou₧itφ operßtor∙ += a new. Nakonec u₧ staΦφ jenom napsat udßlostnφ
proceduru btnTlaΦφtko1_Click, kterß ovÜem musφ disponovat stejn²mi
prvky, jako systΘmov² delegßt (nesmφ vracet hodnotu a musφ pracovat se dv∞ma
parametry typu object a System.EventArgs). Pokud mßte
zkuÜenosti s jazykem C nebo C++, m∙₧ete si delegßta p°edstavit jako
funkΦnφ ukazatel, kter² je ale v jazyce Visual C# zcela typov∞ bezpeΦn².
Delegßt tak ve skuteΦnosti obsahuje runtime adresu funkce, v naÜem
p°φpad∞ zpracovatele udßlosti, a tohoto zpracovatele aktivuje v₧dy, kdy₧ je o
to po₧ßdßn (neboli v₧dy, kdy₧ u₧ivatel klepne na tlaΦφtko). áá ááááá áááááá private
void button1_Click(object
sender, System.EventArgs e) áááááááááááá { ááááááááááááááááááá Button btnTlaΦφtko1 = new Button(); ááááááááááááááááááá btnTlaΦφtko1.Text =
"TlaΦφtko"; ááááááááááááááááááá btnTlaΦφtko1.Location = new Point(10, 100); ááááááááááááááááááá btnTlaΦφtko1.Size = new Size(200, 100); ááááááááááááááááááá this.Controls.Add(btnTlaΦφtko1); ááááááááááááááááááá btnTlaΦφtko1.Click += new System.EventHandler(btnTlaΦφtko1_Click); áááááááááááá } áááááááááááá private
void btnTlaΦφtko1_Click(object sender, EventArgs
e) áááááááááááá { ááááááááááááááááááá MessageBox.Show("Prßv∞
jste klepli na tlaΦφtko."); áááááááááááá } Graficky m∙₧eme vztah mezi udßlostφ, jejφm
zpracovatelem a systΘmov²m delegßtem znßzornit takto: |
Jßn Hanßk