Grafikus C# – Windows Forms tanfolyam › 5.3 lecke Windows Forms · 5.3 lecke · egér Az egér a grafikus programok legfontosabb beviteli eszköze. Egy kattintás mögött azonban több esemény is lezajlik: lenyomás, felengedés, kattintás, dupla kattintás, és mindegyik máskor és másra jó. Ebben a leckében megismered az egéresemények sorrendjét, a Click, DoubleClick és egérműveletek
Click és a MouseClick, az egyszeri és a dupla kattintás különbségét, a kurzor cseréjét, a jobb gombos menüt, a vezérlők egérrel való húzását és a fájlok ablakra ejtését (Drag and Drop).
A lecke végére
- ismered az egéresemények sorrendjét, és megkülönbözteted a
Click,MouseClick,MouseDownésMouseUpeseményt; - tudod, hogy a
Buttonnem kapDoubleClickeseményt, és hogyan kezeld az egyszeri és a dupla kattintás ütközését; - használod a
MouseEnter,MouseLeaveeseményt és aCursortulajdonságot; - jobb gombos menüt kapcsolsz egy vezérlőhöz (
ContextMenuStrip,SourceControl); - vezérlőt húzol egérrel, és fájlokat fogadsz az ablakra (
AllowDrop,DragEnter,DragDrop); - felismered a gyakori hibákat (ugrálás húzáskor, nem működő ejtés, egyszeri és dupla kattintás keveredése).
Mielőtt elkezded
Ehhez a leckéhez az 5.1 és az 5.2 lecke (események, sender, MouseEventArgs) szükséges. Új projektben próbáld ki a példákat.
Az egéresemények sorrendje
Egy egyszerű kattintás nem egyetlen esemény. Az alábbi táblázat a leggyakoribb egéreseményeket foglalja össze:
| Esemény | Mikor fut? | Paraméter |
|---|---|---|
MouseEnter | Az egérkurzor belép a vezérlő területére. | EventArgs |
MouseMove | Az egér mozog a vezérlő felett. | MouseEventArgs |
MouseDown | Egérgombot lenyomtak a vezérlő felett. | MouseEventArgs |
MouseUp | Az egérgombot felengedték. | MouseEventArgs |
Click | Kattintás: lenyomás és felengedés ugyanazon a vezérlőn. | EventArgs |
MouseClick | Ugyanaz, mint a Click, de az egér adataival. | MouseEventArgs |
DoubleClick, MouseDoubleClick | Dupla kattintás (két gyors egymás utáni kattintás). | EventArgs / MouseEventArgs |
MouseHover | Az egér egy ideig mozdulatlanul a vezérlő felett áll. | EventArgs |
MouseLeave | Az egérkurzor elhagyja a vezérlőt. | EventArgs |
MouseWheel | Az egér görgőjét görgetik. | MouseEventArgs |
Click csak annyit mond: „kattintottak”. A MouseClick megmondja azt is, melyik gombbal és hol (e.Button, e.Location). Ha az egérgombra is szükséged van, a MouseClick (vagy a MouseDown) való.MouseDown már a lenyomáskor lefut, a Click csak a felengedés után. Húzáshoz és azonnali reakcióhoz MouseDown, a „végleges” választáshoz Click a jó.Button a bal egérgomb Click eseményét adja, a jobb gombra nem: ehhez a MouseDown/MouseUp/MouseClick kell.Kísérlet: az események sorrendje
Tegyél az ablakra egy lblProba címkét (AutoSize: False, BorderStyle: FixedSingle, méretét nagyítsd meg), egy lstNaplo ListBoxot és egy btnTorol gombot. Az összes eseményt ugyanaz a kód naplózza, így látod a sorrendet:
private void Form1_Load(object sender, EventArgs e)
{
lblProba.MouseEnter += (s, ev) => Naplo("MouseEnter");
lblProba.MouseLeave += (s, ev) => Naplo("MouseLeave");
lblProba.MouseDown += (s, ev) => Naplo("MouseDown (" + ev.Button + ")");
lblProba.MouseUp += (s, ev) => Naplo("MouseUp (" + ev.Button + ")");
lblProba.Click += (s, ev) => Naplo("Click");
lblProba.MouseClick += (s, ev) => Naplo("MouseClick");
lblProba.DoubleClick += (s, ev) => Naplo("DoubleClick");
lblProba.MouseDoubleClick += (s, ev) => Naplo("MouseDoubleClick");
}
private void Naplo(string szoveg)
{
lstNaplo.Items.Add(szoveg);
lstNaplo.TopIndex = lstNaplo.Items.Count - 1; // az utolsó sor látszik
}
private void btnTorol_Click(object sender, EventArgs e)
{
lstNaplo.Items.Clear();
}Jósolj!
A címke fölé viszed az egeret, rákattintasz egyszer a bal gombbal, majd elviszed az egeret. Milyen sorrendben jelennek meg az események a naplóban? Mi változik, ha a jobb gombbal kattintasz?
Jóslat ellenőrzése
Bal gombbal: MouseEnter, MouseDown (Left), MouseUp (Left), Click, MouseClick, MouseLeave. A lenyomás megelőzi a felengedést, a Click a felengedés után fut. Jobb gombbal a MouseDown és a MouseUp Right értékkel fut, a MouseClick is lefut, a Click esemény viszont egyes vezérlőknél csak a bal gombra reagál. Mivel a pontos sorrend a vezérlőtől is függhet, a saját környezetedben mindig érdemes kipróbálni.
Egyszeri és dupla kattintás
A dupla kattintás két gyors egymás utáni kattintás (az időkeretet a Windows egérbeállítása adja meg, ez a SystemInformation.DoubleClickTime, általában 500 ezredmásodperc). A dupla kattintásnál azonban az első kattintás egyszerű kattintásként is lefut, ezért egy dupla kattintás eseményei:
MouseDown,MouseUp,Click,MouseClick(az első kattintás),MouseDown,DoubleClick,MouseDoubleClick,MouseUp(a második kattintás).
A Button nem kap DoubleClick eseményt
A Button vezérlő a gyors egymás utáni két kattintást két egyszeri kattintásként értelmezi: a Click kétszer fut le, a DoubleClick soha. Ha dupla kattintásra kell reagálni, használj Label, Panel, PictureBox, ListBox vagy DataGridView vezérlőt. A Button-nál a dupla kattintás felismeréséhez az időt kellene mérni (lásd a Gyakorlótárat).
Az egyszeri és a dupla kattintás ütközése
Ha egy vezérlőnek mind a Click, mind a DoubleClick eseményére reagálsz, a dupla kattintásnál mindkét művelet lefut: előbb az egyszeri kattintásé, utána a dupláé. Példa: egy fájllistában az egyszeri kattintás kijelöl, a dupla megnyit. Ha az egyszeri kattintás kezelője hosszú vagy zavaró műveletet végez, az a dupla kattintásnál is lefut.
// Jó terv: az egyszeri kattintás csak kijelöl (gyors, ártalmatlan),
// a dupla kattintás megnyit (a kijelölés már megtörtént)
private void lstFajlok_SelectedIndexChanged(object sender, EventArgs e)
{
lblKijelolt.Text = "Kijelölt: " + lstFajlok.Text;
}
private void lstFajlok_DoubleClick(object sender, EventArgs e)
{
if (lstFajlok.SelectedItem != null)
{
MessageBox.Show("Megnyitás: " + lstFajlok.SelectedItem);
}
}Jósolj!
Egy Label Click eseménye egy számlálót növel, a DoubleClick eseménye is. Hányszor nő a számláló egy dupla kattintásra, ha mindkét esemény eggyel növeli?
Jóslat ellenőrzése
Háromszor. Az első kattintás Click eseménye (+1), a második kattintás is Click eseményt vált ki (+1), majd a DoubleClick (+1). A Windows a második kattintást egyszeri kattintásként és dupla kattintásként is jelzi. Ezért a Click és a DoubleClick ugyanarra az objektumra ritkán jó együtt: vagy csak az egyiket használd, vagy az egyszeri kattintás legyen olyan, amely nem zavar a dupla kattintás mellett (például kijelölés).
Kurzor, belépés és kilépés, jobb gombos menü
MouseEnter, MouseLeave és a Cursor
A MouseEnter és a MouseLeave eseményekkel a vezérlő „reagál az egérre” (kiemelés, súgó). A Cursor tulajdonság az egérkurzor alakját adja a vezérlő fölött:
private void Form1_Load(object sender, EventArgs e)
{
lblLink.Cursor = Cursors.Hand; // kéz alakú kurzor, mint a hivatkozásoknál
}
private void lblLink_MouseEnter(object sender, EventArgs e)
{
lblLink.ForeColor = Color.RoyalBlue;
lblLink.Font = new Font(lblLink.Font, FontStyle.Underline);
}
private void lblLink_MouseLeave(object sender, EventArgs e)
{
lblLink.ForeColor = Color.Black;
lblLink.Font = new Font(lblLink.Font, FontStyle.Regular);
}Cursors felsorolás a beépített alakokat adja.Cursors.Default értékre (érdemes try–finally blokkban).SystemInformation.MouseHoverTime) mozdulatlanul áll. Súgóbuborékhoz inkább a ToolTip komponens való (1.11 lecke).A jobb gombos menü
A jobb egérgomb menüje (ContextMenuStrip) a Toolbox Menus & Toolbars csoportjából kerül az ablakra (cmsKartya). Egy vezérlőhöz a ContextMenuStrip tulajdonságával rendeled hozzá, és a jobb kattintásra magától megnyílik. A menüpont eseménykezelője a SourceControl tulajdonságból tudja, melyik vezérlőn nyitották meg a menüt:
// a tervezőben: lblKartya.ContextMenuStrip = cmsKartya;
// a menüpontok: miSzinez (Színezés), miTorles (Törlés)
private void miTorles_Click(object sender, EventArgs e)
{
Control forras = cmsKartya.SourceControl;
if (forras != null)
{
forras.Visible = false;
}
}
private void miSzinez_Click(object sender, EventArgs e)
{
Control forras = cmsKartya.SourceControl;
if (forras != null)
{
forras.BackColor = Color.LightSalmon;
}
}Jósolj!
Három címke is ugyanazt a cmsKartya menüt használja. A menü Törlés menüpontjának kezelőjében nem a SourceControl, hanem a sender paraméter alapján próbálod megtudni, melyik címkén nyitották meg a menüt. Mi lesz a sender?
Jóslat ellenőrzése
A sender a megkattintott menüpont (ToolStripMenuItem), nem a címke. A menüpont nem tudja, melyik címkéhez tartozik a menü, ezért a ContextMenuStrip.SourceControl tulajdonságot kell használni. Ez azt a vezérlőt adja, amelyen a menüt megnyitották.
Húzás és ejtés
Vezérlő húzása egérrel
A vezérlő mozgatásához három esemény kell: a MouseDown megjegyzi, hol fogtad meg, a MouseMove mozgatja, a MouseUp elengedi. A lényeg a fogási pont eltolása (offset): ha a vezérlőt a közepén fogod meg, nem ugorhat a bal felső sarkával az egérhez:
private Label mozgatott = null; // éppen húzott kártya
private Point fogasPont; // hol fogtuk meg (a kártyához képest)
private void Kartya_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left)
{
return;
}
mozgatott = (Label)sender;
fogasPont = e.Location;
mozgatott.BringToFront();
mozgatott.Cursor = Cursors.SizeAll;
}
private void Kartya_MouseMove(object sender, MouseEventArgs e)
{
if (mozgatott == null || mozgatott != sender)
{
return;
}
// az egér helye az ablakhoz képest, mínusz a fogási pont
Point egerAblakban = this.PointToClient(Cursor.Position);
mozgatott.Location = new Point(egerAblakban.X - fogasPont.X, egerAblakban.Y - fogasPont.Y);
}
private void Kartya_MouseUp(object sender, MouseEventArgs e)
{
if (mozgatott != null)
{
mozgatott.Cursor = Cursors.Hand;
mozgatott = null;
}
}MouseMove akkor is megérkezik, ha az egér kimegy a kártyáról.Fájl ejtése az ablakra (Drag and Drop)
A Windowsban a fájlt a Fájlkezelőből az ablakra húzhatod. Ehhez az ablaknak (vagy a vezérlőnek) engedélyeznie kell az ejtést, és két eseményt kell kezelnie: a DragEnter eldönti, elfogadja-e a húzott adatot, a DragDrop feldolgozza:
private void Form1_Load(object sender, EventArgs e)
{
this.AllowDrop = true; // enélkül az ablak nem fogad el semmit
}
private void Form1_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
e.Effect = DragDropEffects.Copy; // az egérkurzor jelzi: elfogadjuk
}
else
{
e.Effect = DragDropEffects.None; // tiltó kurzor
}
}
private void Form1_DragDrop(object sender, DragEventArgs e)
{
string[] fajlok = (string[])e.Data.GetData(DataFormats.FileDrop);
foreach (string fajl in fajlok)
{
lstFajlok.Items.Add(System.IO.Path.GetFileName(fajl));
}
}Form és a vezérlők (például a RichTextBox, ListBox) külön tulajdonsága.GetDataPresent) és milyen hatást jelzünk (e.Effect).string tömb adja (DataFormats.FileDrop).try–catch blokkal.Jósolj!
Az AllowDrop tulajdonságot nem állítod True értékre, de megírod a DragEnter és DragDrop kezelőt, és hozzákötöd. Mi történik, ha egy fájlt az ablakra húzol?
Jóslat ellenőrzése
A tiltó kurzor jelenik meg (áthúzott kör), és egyik esemény sem fut le. Az AllowDrop hiánya a leggyakoribb oka annak, hogy az ejtés nem működik. Ha a kurzor engedélyező (plusz jel), de a DragDrop mégsem fut, valószínűleg a DragEnter kezelő nem állította be az e.Effect értékét.
Mit tegyél ide: egy felvétel az ablakról, amelyen egy fájlt húznak a lista fölé (a plusz jelű kurzorral), mellette a már ejtett fájlok névsora.Javasolt fájlnév: winforms-5-3-ejtes.webp · Alt szöveg: Fájl ejtése az ablakra
Hibakeresés: te vagy a hibadetektív
Mi a baj, és hogyan javítod?
Gondold végig az okot, és csak utána nyisd le a megoldást.
1. A gomb DoubleClick eseménye soha nem fut
Egy A Button DoubleClick kezelője sosem hívódik meg.Ok és javítás
Button a két gyors kattintást két Click eseményként kezeli. Használj Label, Panel vagy PictureBox vezérlőt, vagy mérd az időt két Click között (SystemInformation.DoubleClickTime).
2. Dupla kattintásnál az egyszeri művelet is lefut
Egy listaelem dupla kattintására megnyílik egy ablak, de előtte az egyszeri kattintás is felugrik egy üzenetet. A dupla kattintás első kattintása egyszerű Ok és javítás
Click is. Az egyszeri kattintáshoz csak ártalmatlan műveletet (kijelölés, felirat) rendelj, és a megnyitás/felugró ablak a DoubleClick eseményben legyen.
3. A húzott vezérlő ugrik
mozgatott.Location = e.Location; // a vezérlő bal felső sarka az egérhez ugrikHiba és javítás
Az e.Location a vezérlőhöz képest adja az egér helyét, a Location az ablakhoz képest kell. Számold át az egér helyét az ablakhoz képest (PointToClient(Cursor.Position)), és vond ki a fogási pontot (a MouseDown-nál megjegyzett e.Location).
4. Az ejtés nem működik
A fájl húzásakor tiltó kurzor jelenik meg, és a Ellenőrizd: (1) az DragDrop esemény nem fut le.Ok és javítás
AllowDrop igaz-e azon a vezérlőn, amelyre ejtesz (a Form és a rajta lévő vezérlő külön tulajdonság); (2) a DragEnter kezelő be van-e kötve, és beállítja-e az e.Effect értékét; (3) a felvett eseménykezelő szerkezete helyes-e (DragEventArgs).
5. Az egér gombja nélkül is mozog a kártya
private void Kartya_MouseMove(object sender, MouseEventArgs e)
{
((Label)sender).Left = e.X; // minden egérmozgásra mozog
}Hiba és javítás
A MouseMove minden egérmozgásnál lefut, nemcsak lenyomott gombnál. Használj mozgatott jelzőt (vagy objektumot), amelyet a MouseDown állít be, és a MouseUp töröl. A mozgatást csak akkor végezd, ha a jelző igaz.
6. A menüpont rossz vezérlőt érint
A közös helyi menü Törlés pontja mindig az első kártyát törli. Valószínűleg konkrét kártyára (Ok és javítás
lblKartya1) hivatkoztál a kezelőben. Használd a cmsKartya.SourceControl tulajdonságot, amely azt a vezérlőt adja, amelyen a menüt megnyitották.
Mini projekt: mozgatható kártyák
Készíts programot, amelyben az egér több módon is használható:
- Három
Labelkártya (lblKartya1–lblKartya3,AutoSize: False,BorderStyle: FixedSingle,TextAlign: MiddleCenter, különböző szövegek és színek), kéz alakú kurzorral. - A kártyák bal gombbal húzhatók, a megfogott kártya előre kerül (
BringToFront), és a húzás alattSizeAllkurzor látszik. - A kártya dupla kattintásra színt vált (két szín között váltakozik).
- A jobb gombos menün (
cmsKartya) két pont: Piros (a kártya háttere piros lesz) és Elrejtés (a kártya láthatatlan lesz). A menüpontok aSourceControlalapján működnek. - Egy
btnVisszaallitgomb a rejtett kártyákat visszaállítja és elrendezi a kiindulási helyükre. - Az ablakra ejtett fájlok nevét egy
lstFajlokmutatja (csak fájlok; mappát ne fogadjon el). - Egy
lblInfofelirat az egér ablakbeli helyét mutatja (MouseMoveaz ablakon). - Teszteld: a húzás gyors egérmozgással, a kártyák egymáson, dupla kattintás, mindkét menüpont, fájl és mappa ejtése.
Megoldás megnyitása (próbáld ki előbb önállóan!)
A három kártya mind ugyanazokat a közös kezelőket használja (sender alapján). A kezdeti helyeket a Form1_Load eltárolja, hogy a gomb visszaállíthassa őket. A mappa ejtését a System.IO.Directory.Exists szűri ki.
private Label mozgatott = null;
private Point fogasPont;
private Point[] kezdoHelyek = new Point[3];
private Label[] kartyak;
private void Form1_Load(object sender, EventArgs e)
{
kartyak = new Label[] { lblKartya1, lblKartya2, lblKartya3 };
for (int i = 0; i < kartyak.Length; i++)
{
kezdoHelyek[i] = kartyak[i].Location;
kartyak[i].Cursor = Cursors.Hand;
}
this.AllowDrop = true;
}
private void Kartya_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left)
{
return;
}
mozgatott = (Label)sender;
fogasPont = e.Location;
mozgatott.BringToFront();
mozgatott.Cursor = Cursors.SizeAll;
}
private void Kartya_MouseMove(object sender, MouseEventArgs e)
{
if (mozgatott == null || mozgatott != sender)
{
return;
}
Point egerAblakban = this.PointToClient(Cursor.Position);
mozgatott.Location = new Point(egerAblakban.X - fogasPont.X, egerAblakban.Y - fogasPont.Y);
}
private void Kartya_MouseUp(object sender, MouseEventArgs e)
{
if (mozgatott != null)
{
mozgatott.Cursor = Cursors.Hand;
mozgatott = null;
}
}
private void Kartya_DoubleClick(object sender, EventArgs e)
{
Label kartya = (Label)sender;
kartya.BackColor = kartya.BackColor == Color.LightSkyBlue ? Color.Khaki : Color.LightSkyBlue;
}
private void miPiros_Click(object sender, EventArgs e)
{
Control forras = cmsKartya.SourceControl;
if (forras != null)
{
forras.BackColor = Color.IndianRed;
}
}
private void miElrejtes_Click(object sender, EventArgs e)
{
Control forras = cmsKartya.SourceControl;
if (forras != null)
{
forras.Visible = false;
}
}
private void btnVisszaallit_Click(object sender, EventArgs e)
{
for (int i = 0; i < kartyak.Length; i++)
{
kartyak[i].Visible = true;
kartyak[i].Location = kezdoHelyek[i];
}
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
lblInfo.Text = $"Egér: {e.X}, {e.Y}";
}
private void Form1_DragEnter(object sender, DragEventArgs e)
{
e.Effect = e.Data.GetDataPresent(DataFormats.FileDrop) ? DragDropEffects.Copy : DragDropEffects.None;
}
private void Form1_DragDrop(object sender, DragEventArgs e)
{
string[] elemek = (string[])e.Data.GetData(DataFormats.FileDrop);
foreach (string elem in elemek)
{
if (System.IO.Directory.Exists(elem))
{
continue; // mappát nem fogadunk el
}
lstFajlok.Items.Add(System.IO.Path.GetFileName(elem));
}
}Mit tegyél ide: a kész program három, egymást részben takaró kártyával, az egyik kártya húzás közben, mellette a jobb oldali lista néhány ejtett fájlnévvel.Javasolt fájlnév: winforms-5-3-kesz.webp · Alt szöveg: A mozgatható kártyák programja
Három önálló gyakorlófeladat
Egyszerre csak egyet csinálj: tervezd meg, írd meg, futtasd, ellenőrizd, és csak utána nyisd ki a megoldást.
1. Eseménysorrend-naplózó a Buttonon
Ismételd meg a leckebeli kísérletet egy A Button vezérlőn. Mit tapasztalsz dupla kattintáskor? Mi a különbség a Label eredményéhez képest?Egy lehetséges megoldás
Button esetében dupla kattintáskor két Click (és MouseClick) esemény lefut, de a DoubleClick és a MouseDoubleClick nem. A Label a második kattintásnál DoubleClick és MouseDoubleClick eseményt is jelez. A kísérlet kódja azonos, csak a vezérlő neve változik.
2. Fájl ejtése a szövegmezőbe
A A rtbSzoveg RichTextBoxra ejtett TXT fájl tartalma töltődjön be a szövegmezőbe. Más kiterjesztésű fájlnál üzenet jelenjen meg.Egy lehetséges megoldás
RichTextBox AllowDrop tulajdonságát True értékre kell állítani (a vezérlőé, nem csak az ablaké). A DragDrop kezelőben a kiterjesztést a Path.GetExtension adja, a tartalmat a File.ReadAllText. A hibákat try–catch kezeli.private void rtbSzoveg_DragEnter(object sender, DragEventArgs e)
{
e.Effect = e.Data.GetDataPresent(DataFormats.FileDrop) ? DragDropEffects.Copy : DragDropEffects.None;
}
private void rtbSzoveg_DragDrop(object sender, DragEventArgs e)
{
string[] fajlok = (string[])e.Data.GetData(DataFormats.FileDrop);
string fajl = fajlok[0];
if (System.IO.Path.GetExtension(fajl).ToLower() != ".txt")
{
MessageBox.Show("Csak TXT fájlt lehet ejteni.");
return;
}
try
{
rtbSzoveg.Text = System.IO.File.ReadAllText(fajl);
}
catch (Exception ex)
{
MessageBox.Show("A fájl nem olvasható: " + ex.Message);
}
}
3. Kattintásszámláló gombonként
Egy A pnlTer panelen a bal gomb a lblBal, a jobb gomb a lblJobb, a középső a lblKozep számlálóját növelje. A dupla kattintás a bal számlálót egyszerre csak eggyel növelje (ne háromszor).Egy lehetséges megoldás
MouseClick eseményt használjuk, amelynek e.Button megmondja a gombot, és a MouseDoubleClick nélkül dolgozunk. A második, dupla kattintás is MouseClick esemény, ezért a bal számláló dupla kattintásnál kettővel nő, ami természetes (két kattintás volt). Az e.Clicks értéke 2 a második kattintásnál, így azt is megkülönböztetheted.private int bal = 0;
private int jobb = 0;
private int kozep = 0;
private void pnlTer_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
bal = bal + 1;
lblBal.Text = "Bal: " + bal;
}
else if (e.Button == MouseButtons.Right)
{
jobb = jobb + 1;
lblJobb.Text = "Jobb: " + jobb;
}
else if (e.Button == MouseButtons.Middle)
{
kozep = kozep + 1;
lblKozep.Text = "Közép: " + kozep;
}
}
Gyakorlótár: 6 további feladat
Három szinten gyakorolhatsz: alap, közepes és kihívás. Csak a próbálkozás után nyisd le a megoldást.
Alap szint
1. Kéz alakú kurzor
Egy A pbLogo PictureBox fölött az egérkurzor legyen kéz alakú, és a kattintásra nyíljon meg a böngésző egy címmel. Mit kell az URL megnyitásához tenni?Megoldás megnyitása
Cursor tulajdonság egyszer állítható a tervezőben. A böngésző megnyitásához a Process.Start kell, a mai .NET-ben a UseShellExecute bekapcsolásával (a .NET Frameworkben az egyszerű forma elég). A címet csak megbízható forrásból, a programba írva használd.private void Form1_Load(object sender, EventArgs e)
{
pbLogo.Cursor = Cursors.Hand;
}
private void pbLogo_Click(object sender, EventArgs e)
{
System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo
{
FileName = "https://www.digitalisfelfedezok.hu",
UseShellExecute = true
});
}
2. Kiemelés egérrel
Három Közös Label (lblA, lblB, lblC) háttere sárga legyen, amíg az egér fölötte van, és álljon vissza, ha elhagyja. Hogyan oldod meg három külön kód nélkül?Megoldás megnyitása
MouseEnter és MouseLeave kezelő, a sender alapján. Az eredeti színt a Tag tulajdonságban jegyezzük meg (az 1.4 lecke óta ismert eszköz), hogy minden címke a saját színére álljon vissza.private void Cimke_MouseEnter(object sender, EventArgs e)
{
Label cimke = (Label)sender;
cimke.Tag = cimke.BackColor; // az eredeti szín megjegyzése
cimke.BackColor = Color.Yellow;
}
private void Cimke_MouseLeave(object sender, EventArgs e)
{
Label cimke = (Label)sender;
if (cimke.Tag is Color eredeti)
{
cimke.BackColor = eredeti;
}
}
Közepes szint
3. Egyszeri és dupla kattintás megkülönböztetése
Egy Az egyszeri kattintás kezelése késleltetve történik: egy pnlGomb panelen az egyszeri kattintás a Egy, a dupla a Kettő szöveget írja a feliratra, és dupla kattintásnál az Egy ne jelenjen meg. Hogyan oldod meg?Megoldás megnyitása
Timer a dupla kattintás idejéig vár (SystemInformation.DoubleClickTime). Ha közben jön a második kattintás (DoubleClick), a Timer-t leállítjuk, és a Kettő felirat jelenik meg. Ha a Timer lejár, az egyszeri kattintás érvényes.private void Form1_Load(object sender, EventArgs e)
{
tmrKattintas.Interval = SystemInformation.DoubleClickTime;
}
private void pnlGomb_Click(object sender, EventArgs e)
{
tmrKattintas.Stop();
tmrKattintas.Start(); // az egyszeri kattintás eredménye késik
}
private void tmrKattintas_Tick(object sender, EventArgs e)
{
tmrKattintas.Stop();
lblEredmeny.Text = "Egy";
}
private void pnlGomb_DoubleClick(object sender, EventArgs e)
{
tmrKattintas.Stop();
lblEredmeny.Text = "Kettő";
}
4. Keret nélküli ablak mozgatása
Egy keret nélküli ablakot ( A képernyő-koordinátákkal dolgozunk (FormBorderStyle: None) a pnlCim címsáv panelről lehessen húzással mozgatni. Hogyan számolod az ablak új helyét?Megoldás megnyitása
Cursor.Position): az egér elmozdulását a lenyomáskori helyhez képest hozzáadjuk az ablak kezdeti helyéhez. Ha az ablak mozog, az ablakhoz viszonyított koordináták (e.Location) is változnának, ezért a képernyő-koordináta a megbízható.private bool mozog = false;
private Point kezdoEger;
private Point kezdoAblak;
private void pnlCim_MouseDown(object sender, MouseEventArgs e)
{
mozog = true;
kezdoEger = Cursor.Position;
kezdoAblak = this.Location;
}
private void pnlCim_MouseMove(object sender, MouseEventArgs e)
{
if (!mozog)
{
return;
}
this.Location = new Point(
kezdoAblak.X + Cursor.Position.X - kezdoEger.X,
kezdoAblak.Y + Cursor.Position.Y - kezdoEger.Y);
}
private void pnlCim_MouseUp(object sender, MouseEventArgs e)
{
mozog = false;
}
Kihívás szint
5. Elemek húzása két lista között
Két A húzás indítása a ListBox (lstBal, lstJobb) között húzással lehessen elemet áthelyezni. Mit kell beállítanod, és melyik eseményben indítod a húzást?Megoldás megnyitása
DoDragDrop metódussal történik a MouseDown eseményben (a kijelölt elemmel). Mindkét lista AllowDrop tulajdonsága igaz. A DragEnter engedélyezi, a DragDrop felveszi az elemet, és a forráslistából törli. A forrást a DragEventArgs adatából vagy egy mezőből tudjuk meg.private ListBox forras = null;
private void Lista_MouseDown(object sender, MouseEventArgs e)
{
ListBox lista = (ListBox)sender;
int index = lista.IndexFromPoint(e.Location);
if (index == ListBox.NoMatches)
{
return;
}
forras = lista;
lista.DoDragDrop(lista.Items[index].ToString(), DragDropEffects.Move);
}
private void Lista_DragEnter(object sender, DragEventArgs e)
{
e.Effect = e.Data.GetDataPresent(DataFormats.Text) ? DragDropEffects.Move : DragDropEffects.None;
}
private void Lista_DragDrop(object sender, DragEventArgs e)
{
ListBox cel = (ListBox)sender;
if (cel == forras)
{
return;
}
string elem = (string)e.Data.GetData(DataFormats.Text);
cel.Items.Add(elem);
forras.Items.Remove(elem);
}
6. Nagyítás Ctrl + görgetéssel
Egy Az egéreseményben az rtbSzoveg RichTextBoxban a Ctrl + egérgörgő a szöveg nagyítását (a ZoomFactor) változtassa 0,5 és 3 között. Hogyan tudod meg, hogy a Ctrl le van-e nyomva egér esemény közben?Megoldás megnyitása
e nem tartalmazza a módosítókat, ezért a Control.ModifierKeys statikus tulajdonságot kérdezzük le. A RichTextBox a Ctrl+görgetést alapból is képes nagyításként kezelni, ezért a megoldást érdemes kipróbálni, és ha az alapműködés és a saját kód ütközik (kétszeres nagyítás), a ZoomFactor saját kezelését a RichTextBox helyett egy másik vezérlőn próbáld ki.private void Form1_Load(object sender, EventArgs e)
{
rtbSzoveg.MouseWheel += rtbSzoveg_MouseWheel;
}
private void rtbSzoveg_MouseWheel(object sender, MouseEventArgs e)
{
if (Control.ModifierKeys != Keys.Control)
{
return;
}
float uj = rtbSzoveg.ZoomFactor + (e.Delta > 0 ? 0.1f : -0.1f);
rtbSzoveg.ZoomFactor = Math.Max(0.5f, Math.Min(3f, uj));
}
Gyors önellenőrzés
Válaszolj fejben, és csak utána nyisd le a választ. MouseEnter (belépéskor), MouseDown, MouseUp, Click, MouseClick, majd MouseLeave (kilépéskor). A pontos sorrendet a vezérlő is befolyásolhatja, ezért érdemes kipróbálni. A A Az első kattintás után a A Az A 1. Mi az egéresemények sorrendje egy kattintásnál?
2. Mi a különbség a Click és a MouseClick között?
Click EventArgs-ot kap (nincs gomb- és helyadat), a MouseClick MouseEventArgs-ot (gomb, hely).3. Miért nem működik a Button DoubleClick eseménye?
Button a gyors kattintásokat egyszeri kattintásokként (két Click) kezeli. Dupla kattintáshoz Label, Panel, PictureBox vagy lista való.4. Mi történik dupla kattintáskor a Click eseménnyel?
Click lefut, és a második kattintás is jelezhet Click eseményt, majd jön a DoubleClick. Az egyszeri kattintáshoz ezért ártalmatlan műveletet rendelj.5. Hogyan húzol egy vezérlőt úgy, hogy ne ugorjon?
MouseDown-nál megjegyzed a fogási pontot (e.Location), mozgatáskor az egér ablakbeli helyéből kivonod, és úgy állítod be a Location értéket.6. Mi kell ahhoz, hogy egy fájlt az ablakra lehessen ejteni?
AllowDrop = true, a DragEnter kezelő (e.Effect beállítása) és a DragDrop kezelő (a DataFormats.FileDrop adatból).7. Hogyan derül ki a helyi menü eseményében, melyik vezérlőn nyitották meg?
ContextMenuStrip.SourceControl tulajdonságból. A sender a menüpont, nem a vezérlő.
Mit tudsz már?
- Ismered az egéresemények sorrendjét és a
Click/MouseClick/DoubleClickkülönbségét. - Tudod, hogyan kezeld az egyszeri és a dupla kattintás ütközését.
- Kurzort cserélsz, és jobb gombos menüt használsz a
SourceControlsegítségével. - Vezérlőt húzol egérrel, és fájlokat fogadsz az ablakra.
- Felismered a gyakori egérkezelési hibákat.
Következő lecke: KeyDown, KeyPress, KeyUp és gyorsbillentyűk
Az egér után a billentyűzet következik: a három billentyűesemény különbsége, a gyorsbillentyűk és a menük billentyűkombinációi.




