Myš a klávesnice
• Nejzajímavější jsou události MouseDown a KeyDown.
• Z objektu e, který je parametrem obslužné metody MouseDown a KeyDown, lze zjistit, které tlačítko myši bylo stisknuto a pozice myši, a jaká klávesa na klávesnici byla stisknuta.
• MouseDown
– e.Button – výčet Mouse.Buttons, určuje, které tlačítko stisknuto
– e.X, e.Y – int, souřadnice myši v okamžiku stisku, vztahují se k souřadnému systému objektu, co událost vyvolal (oknoProgramu)
• KeyDown
– e.Control, e.Alt, e.Shift – bool, určuje, zda stisknut Ctrl, Alt, Shift
– e.Keycode – výčet Keys, určuje stisknutou klávesu
• Př. program, který počítá stisky levého a pravého tlačítka, musí fungovat nad ovládacími prvky i mimo.
private void všechnyPrvky_MouseDown(object sender, MouseEventArgs e) { // Zvětši počitadlo levého tlačítka if (e.Button == MouseButtons.Left) { int kolikrát = Convert.ToInt32(poleLevéTlačítko.Text); kolikrát++; poleLevéTlačítko.Text = kolikrát.ToString(); } // Zvětši počitadlo pravého tlačítka if (e.Button == MouseButtons.Right) { int kolikrát = Convert.ToInt32(polePravéTlačítko.Text); kolikrát++; polePravéTlačítko.Text = kolikrát.ToString(); } }
private void oknoProgramu_KeyDown(object sender, KeyEventArgs e)
{
// Test modifikačních kláves
string modif = null;
if (e.Control)
modif += "Ctrl+";
if (e.Alt)
modif += "Alt+";
if (e.Shift)
modif += "Shift+";
// Modifikační klávesy podruhé do zprávy nepřidávat
string klávesa;
if (e.KeyCode == Keys.ControlKey ||
e.KeyCode == Keys.Menu ||
e.KeyCode == Keys.ShiftKey)
klávesa = null;
else
klávesa = e.KeyCode.ToString();
// Zobrazení zprávy
info.Text = "Stisknuta klávesa " + modif + klávesa;
}
private void oknoProgramu_MouseDown(object sender, MouseEventArgs e)
{
// Zjištění tlačítka, které bylo stisknuto
string jaké;
switch (e.Button)
{
case MouseButtons.Left:
jaké = "Levé";
break;
case MouseButtons.Middle:
jaké = "Prostřední";
break;
case MouseButtons.Right:
jaké = "Pravé";
break;
default: // Pokud nic z předchozího nenastane
jaké = "Neznámé";
break;
}
// Zjištění souřadnic
int myšX = e.X;
int myšY = e.Y;
// Zobrazení zprávy
info.Text = jaké + " tlačítko stisknuto na souřadnicích [" +
myšX.ToString() + ";" + myšY.ToString() + "]";
}
Př. Test myši a klávesnice – dole label jménem info
• Př. program, který náhodně kreslí na sekundu modré kuličky a píše, kolik kuliček bylo zobrazeno a kolik zasaženo myší.
Paint – vykreslí kuličku v barvě uložené v příslušné členské proměnné.
Tick – vygeneruje nové souřadnice, nastaví se modrá barva kuličky, překreslí se panel a zvedne počitadlo kuliček
MouseDown – vyhodnotí se, zda stisknuta myš na kuličce nebo mimo, pokud zásah, tak obarvení kuličky, zvětší počitadlo zásahů
• Detekce zásahu – vzdálenost od středu kuličky k místu klepnutí musí být menší nebo rovna poloměru kuličky. Vzdálenost klepnutí od středu kuličky vypočítáme pomocí Pythágorovy věty.
x
y
S
dSK
K
y
x
22 )()( yx
using System; using System.Drawing; using System.Windows.Forms; namespace Trefuj_kuličky { public partial class oknoProgramu : Form { Random náhoda = new Random(); // Souřadnice, poloměr a aktuální barva kuličky: int x, y; int poloměr = 5; Color barva = Color.Transparent; // na začátku průhledná // Možné barvy kuličky Color barvaNezasažené = Color.CornflowerBlue; Color barvaZasažené = Color.Tomato; public oknoProgramu() { InitializeComponent(); } private void časovač_Tick(object sender, EventArgs e) { // Stanovím meze, ve kterých se může nacházet střed // kuličky tak, aby kulička byla celá uvnitř int minX = poloměr; int maxX = panel.Width - poloměr - 1; int minY = poloměr; int maxY = panel.Height - poloměr - 1; // Připravím novou kuličku x = náhoda.Next(minX, maxX + 1); y = náhoda.Next(minY, maxY + 1); barva = barvaNezasažené; panel.Refresh(); // Aktualizuji počitadlo kuliček (zvětším o 1) int početKuliček = Convert.ToInt32(poleKuliček.Text); početKuliček++; poleKuliček.Text = početKuliček.ToString(); } private void panel_Paint(object sender, PaintEventArgs e) { Graphics kp = e.Graphics; // Nakreslím kuličku se středem v bodě [x, y] a barvou barva int xLH = x - poloměr; int yLH = y - poloměr; int šířka = 2 * poloměr; int výška = šířka; Brush štětec = new SolidBrush(barva);
Brush štětec = new SolidBrush(barva);
kp.FillEllipse(štětec, xLH, yLH, šířka, výška);
}
private void panel_MouseDown(object sender, MouseEventArgs e)
{
// Pokud byla poslední kulička již zasažena, ignoruji myš
if (barva != barvaNezasažené)
return;
// Vyhodnotím, zda došlo k zásahu
int rozdílX = e.X - x;
int rozdílY = e.Y - y;
double vzdálenostOdStředu = Math.Sqrt(rozdílX*rozdílX + rozdílY*rozdílY);
bool zásah = vzdálenostOdStředu
Konzumace kláves • Při vyhodnocování stisknutých kláves je problém, že
některé ovládací prvky převezmou klávesy a zpracují je samy a na okno programu už nedojde řada. Např. textová pole, zaškrtávátka apod.
• Př. program, který vypisuje stisknuté klávesy a navíc nastavuje zaškrtávátko, je-li stisknuto F1 až F12.
private void oknoProgramu_KeyDown(object sender, KeyEventArgs e) { Keys klávesa = e.KeyCode; info.Text = "Stisknuta klávesa " + klávesa.ToString(); políčkoFunkčníKlávesa.Checked = klávesa >= Keys.F1 && klávesa
• Opravit lze nastavením vlastnosti KeyPreview okna na true, čímž docílíme, že okno dostane stisknuté klávesy dříve než prvek.
• Vyzkoušíme…
• Ovšem stále nefungují klávesy jako šipky, Tab, mezerník apod.
• Šipky a tabulátor mají v programu navigační funkci, takže jsou zpracovány jinak, než předáním ovládacímu prvku.
• Mezerník program pozná, ale zároveň ho zpracovává i zaškrtávací políčko, takže to mylně pak vypadá, že jde o funkční klávesu.
• Zaškrtávátko (příp. všechny prvky, je-li jich v programu víc) prohlásí, že chtějí všechny klávesy brát jako vstupní a nikoliv jako navigační.
• Mezerník se zpracuje v události PreviewKeyDown a označí se jako zpracovaný, takže dále se jím již nikdo nezabývá.
• Jak se toto řeší, ukazuje následující výpis.
private void oknoProgramu_KeyDown(object sender, KeyEventArgs e) { Keys klávesa = e.KeyCode; info.Text = "Stisknuta klávesa " + klávesa.ToString(); políčkoFunkčníKlávesa.Checked = klávesa >= Keys.F1 && klávesa
Parametr Sender
• předává odkaz na prvek, který událost vyvolal
• využívá se hlavně tehdy, když jedna metoda obsluhuje události více objektů
• Př. starý známý barevný prstenec
private void tlačítka_Click(object sender, EventArgs e)
{
Button stisknutéTlačítko = (Button)sender;
barva = stisknutéTlačítko.BackColor;
panel.Refresh();
}
• Př. program s devíti tlačítky, která se po stisknutí ztrácejí, poslední zároveň ukončí program, všechna tlačítka musí obsluhovat jediná společná metoda
• Př. vyrobte program, který umožní tahat čtverec myší
• Tip: obsluhujte MouseDown, MouseUp a MouseMove, pracujte s e.X a e.Y
using System; using System.Drawing; using System.Windows.Forms; namespace Tažení_myší { public partial class oknoProgramu : Form { // Parametry čtverce int xLeváČtverce, yHorníČtverce; int velikostČtverce = 50; // Pozice myši vůči levému hornímu rohu čtverce int xPosunMyši, yPosunMyši; // Jestli probíhá tažení bool tažení = false; public oknoProgramu() { InitializeComponent(); } private void oknoProgramu_Load(object sender, EventArgs e) { xLeváČtverce = (ClientSize.Width - velikostČtverce) / 2; yHorníČtverce = (ClientSize.Height - velikostČtverce) / 2; } private void oknoProgramu_Paint(object sender, PaintEventArgs e) { Graphics kp = e.Graphics; kp.FillRectangle(Brushes.LightCoral, xLeváČtverce, yHorníČtverce, velikostČtverce, velikostČtverce); } private void oknoProgramu_MouseDown(object sender, MouseEventArgs e) { // Pozice myši vůči oknu int xMyši = e.X; int yMyši = e.Y; // int xPraváČtverce = xLeváČtverce + velikostČtverce - 1; int yDolníČtverce = yHorníČtverce + velikostČtverce - 1;
// Je myš stisknuta nad čtvercem? if (xMyši >= xLeváČtverce && xMyši = yHorníČtverce && yMyši
• Př. program, který pomocí šipek nahoru a dolů emuluje funkci číselníku
• Př. program Půlkalkulačka, který do textového pole sestaví zadané číslo pomocí kláves. Všechny klávesy musí obsluhovat jedna metoda.