Programování v prostředí.net Winforms 1 / 60
Obsah přednášky Windows forms Formuláře Kontrolky Prostředí Validace vstupů Tooltipy Menu Standardní dialogy 2 / 60
Windows forms Shrnující název pro množinu tríd umožnující tvorbu grafických uživatelských rozhraní Součást.NET Frameworku Součást standardu 3 / 60
Jmenné prostory System.Windows.Forms obsahuje formuláře, kontrolky, dialogy System.Drawing Kreslení, GDI+ System.Drawing.Imaging rozšířené možnosti práce s grafikou Nutno přidat reference dělá automaticky vývojové prostředí 4 / 60
Aplikace Třída Application poskytuje statické metody a události pro událostmi řízené programování Application.Run(Form) zobrazí formulář a zahájí smyčku událostí blokuje, dokud nedojde k uzavření formuláře Application.Exit() ukončí smyčku událostí zavře všechny okna aplikace Application.[User Common]AppData[Path Registry] vrátí cesty k adresářům s uživatelskými daty C:/Documents and Settings/All users/data aplikací/<company name>/<product name>/<product version> 5 / 60
Aplikace příklad namespace Kiv. Net. Lesson06 class Program static void Main ( string [] args ) Form form = new Form (); Application. Run ( form ); 6 / 60
Třída Form Třída Form reprezentuje formulář (okno) Obvykle se dědí od Windows.Forms.Form přidají se ovládací prvky přidají se reakce na události 7 / 60
Metody Show zobrazí formulář (program pak pokračuje v běhu) ShowDialog zobrazí formulář (čeká dokud se formulář nezavře) Close zavře formulář Hide skryje formulář Activate zobrazí skrytý formulář 8 / 60
Události Load při zobrazení pomocí Show, ShowDialog Activated když se stane aktivní Activate Deactivate když se stane neaktivní Hide FormClosing okno se zavírá lze zrušit pomocí CancelEvenArgs FormClosed okno se definitivně zavírá 9 / 60
Příklad namespace Kiv. Net. Lesson06 class NonClosingForm : Form public NonClosingForm () this. FormClosing += new FormClosingEventHandler ( NonClosingForm_ FormClosing ); void NonClosingForm_ FormClosing ( object sender, FormClosingEventArgs e) e. Cancel = true ; class Program static void Main ( string [] args ) NonClosingForm form = new NonClosingForm (); form. ShowDialog (); 10 / 60
Nemodální formulář Zobrazí se metodou Show Vlastní smyčka zpráv žije si vlastním životem v aplikaci jich může být několik Může mít vlastníka při skrytí, uzavření či aktivaci vlatníka udělá totéž kreslí se přes vlastníka 11 / 60
Modální formulář dialog Zobrazí se metodou ShowDialog Dokud není uzavřen, nedovolí uživateli manipulovat s rodičem Matoda ShowDialog vrací hodnotu výčtový typ DialogResult Yes, No, Abort... 12 / 60
Modální formulář předání hodnoty Nastavení hodnoty v property DialogResult způsobí uzavření formuláře Nastavení hodnoty DialogResult u některého z tlačítek formuláře není třeba psát obsluhu pro tlačítko funguje automaticky 13 / 60
Třída Control Třída Control je předek všech vizuálních prvků včetně formuláře Umožňuje zobrazení a skrytí nastavení pozice a velikosti vnořování kontrolek reakce na události práci ve vláknech 14 / 60
Některé kontrolky 15 / 60
Pozice a velikost Jednotlivé veličiny pozice horní hrany Top pozice levé hrany Left šířka kontrolky Width výška kontrolky Height dolní a pravá hrana pouze pro čtení (Right, Bottom) Velikost a pozice dvojice výška, šířka Size (SizeF) dvojice levý, horní Point (PointF) Kompletní určení velikosti struktura Rectangle (RectangleF) 16 / 60
Velikost kontrolky a klientská oblast Velikost kontrolky celková velikost Width, Height, Size Klientská oblast vnitřek kontrolky bez rámečků, rolovacích lišt, menu... ClientWidth, ClientHeight, ClientSize 17 / 60
Vnořování kontrolek Property ControlCollectoin Controls metoda Add přidá kontrolku metoda Remove vyjme kontrolku indexer Controls[int/string] vrátí referenci na kontrolku Kontrolka se musí přidat, aby se zobrazila kontrolky se většinou vytváří jako private členy formuláře (nejsou přístupné zvenku) 18 / 60
Příklad class ButtonForm : Form private Button button ; public ButtonForm () button = new Button (); this. Controls. Add ( button ); 19 / 60
Chování vnořených kontrolek Pozice se vztahuje k levému hornímu rohu klientské oblasti rodiče Vykreslují se vždy přes rodičovskou kontrolku u sesterských kontrolek záleží na Z-pořadí standardně podle pořadí přidání do kolekce kontrolek BringToFront posune kontrolku nejblíž SendToBack odsune kontrolku nejdál Přebírají některé vlastnosti (ambientní vlastnosti) barva, font... 20 / 60
Události Jsou řešeny pomocí delegátů na metody, které danou událost zpracují button. click += new System. EventHandler ( buttonclick ); void buttonclick ( object sender, System. EventArgs e) this. Close (); Událost je zaslána kontrolkou nad kterou k události došlo (sender) Odesílatel nezná příjemce Příjemce zná odesílatele Další informace jsou uloženy v EventArgs 21 / 60
Obsluha Události od více kontrolek může obsluhovat jediná metoda V některých případech může jedna metoda obsluhovat i různé události Příklad obsluhy button1. Click += new System. EventHandler ( button1_ Click ); button2. Click += new System. EventHandler ( button1_ Click );... private void button1_ Click ( object sender, System. EventArgs e) MessageBox. Show (" kliklo se na " +(( Button ) sender ). Text ); 22 / 60
Klávesnice KeyDown, KeyUp argument události obsahuje scan kód klávesy funguje i pro neznakové klávesy modifikátory Control, Alt, Shift KeyPress jen pro znakové klávesy vrací kód znaku V případě stisknuté klávesy nastává střídavě události KeyDown a KeyPress, událost KeyUp nastane až při uvolnění klávesy 23 / 60
Myš Click a DoubleClick nemusí být nutně od myší, ale například po stisku klávesy ENTER pouze informuje, že událost nastala, argument nenese informaci o souřadnicích myši MouseClick a MouseDoubleClick nově v.net 2.0 podobně jako Click, ale pouze pro myš MouseEnter, MouseHover a MouseLeave pouze informují o události MouseMove, MouseDown, MouseUp a MouseWheel argument události (MouseEventArgs) nese informaci o pozici myši a stavu tlačítek a kolečka 24 / 60
Vlákna Čtení či zápis dat kontrolky z jiného vlákna může způsobit nekonzistenci v.net 2.0 vyhodí InvalidOperationException vláknově bezpečné metody: (Begin/End)Invoke přístup z jiného vlákna indikuje InvokeRequire Synchronní způsob blokující volání Invoke(delegate, object[]) zavolá delegáta vláknem, kterému patří kontrolka předá pole objektů jako argumenty vrátí hodnotu, kterou vrátil delegát 25 / 60
Synchronní způsob public ThreadForm () button1 = new Button (); thread1 = new Thread ( new ThreadStart ( CountingThread ));... protected void CountingThread ()... // slozity vypocet //!!! vyjímka!!! button1. Text = mezivysledek ;... 26 / 60
Synchronní způsob public ThreadForm () button1 = new Button (); thread1 = new Thread ( new ThreadStart ( CountingThread ));... protected void CountingThread ()... // slozity vypocet MethodInvoker settext = delegate () button1. Text = mezivysledek ; ; button1. Invoke ( settext );... 26 / 60
Synchronní způsob public ThreadForm () button1 = new Button (); thread1 = new Thread ( new ThreadStart ( CountingThread ));... protected void CountingThread ()... // slozity vypocet SetText ( mezivysledek );... protected delegate void SetTextDelegate ( string text ); protected void SetText ( string text ) if ( button1. InvokeRequired ) SetTextDelegate settext = new SetTextDelegate ( SetText ); button1. Invoke ( settext, new object [] text ); else button1. Text = text ; 26 / 60
Asynchronní invoke BeginInvoke(delegate, object[]) požádá o zavolání delegáta není blokující zařadí požadavek do fronty a pokračuje v běhu vrátí instanci třídy implementující IAsyncResult EndInvoke(IAsyncResult) je blokující vrací návratou hodnotu metody předané v delegátu 27 / 60
Asynchronní způsob public ThreadForm () button1 = new Button (); thread1 = new Thread ( new ThreadStart ( CountingThread ));... protected void CountingThread ()... // slozity vypocet BeginInvoke ( new SetTextDelegate ( SetText ), new object [] mezivysledek );... protected delegate void SetTextDelegate ( string text ); protected void SetText ( string text ) button1. Text = text ; 28 / 60
Složitá aplikace class ComplexForm : Form public ComplexForm () 29 / 60
Složitá aplikace class ComplexForm : Form protected Button closebutton ; public ComplexForm () closebutton = new Button (); this. Controls. Add ( closebutton ); 29 / 60
Složitá aplikace class ComplexForm : Form protected Button closebutton ; public ComplexForm () closebutton = new Button (); closebutton. Click += new EventHandler ( closebutton_ Click ); this. Controls. Add ( closebutton ); void closebutton_ Click ( object sender, EventArgs e) this. Close (); 29 / 60
Složitá aplikace class ComplexForm : Form protected Button closebutton ; public ComplexForm () closebutton = new Button (); closebutton. Text = " Zavřít "; closebutton. Name = " closebutton "; closebutton. Left = 110; closebutton. Top = 40; closebutton. Width = 90; closebutton. Height = 20; closebutton. Click += new EventHandler ( closebutton_click ); this. Controls. Add ( closebutton ); void closebutton_click ( object sender, EventArgs e) this. Close (); 29 / 60
Složitá aplikace class ComplexForm : Form protected Button openbutton ; protected Button closebutton ; public ComplexForm () openbutton = new Button (); openbutton. Text = " Otevřít "; openbutton. Name = " openbutton "; openbutton. Left = 10; openbutton. Top = 40; openbutton. Width = 90; openbutton. Height = 20; openbutton. Click += new EventHandler ( openbutton_click ); this. Controls. Add ( openbutton ); closebutton = new Button (); closebutton. Text = " Zavřít "; closebutton. Name = " closebutton "; closebutton. Left = 110; closebutton. Top = 40; closebutton. Width = 90; closebutton. Height = 20; closebutton. Click += new EventHandler ( closebutton_click ); this. Controls. Add ( closebutton ); void openbutton_click ( object sender, EventArgs e) new ComplexForm (). ShowDialog (); void closebutton_click ( object sender, EventArgs e) this. Close (); 29 / 60
Složitá aplikace class ComplexForm : Form protected Button openbutton ; protected Button closebutton ; protected Label questionlabel ; public ComplexForm () openbutton = new Button (); openbutton. Text = " Otevřít "; openbutton. Name = " openbutton "; openbutton. Left = 10; openbutton. Top = 40; openbutton. Width = 90; openbutton. Height = 20; openbutton. Click += new EventHandler ( openbutton_click ); this. Controls. Add ( openbutton ); closebutton = new Button (); closebutton. Text = " Zavřít "; closebutton. Name = " closebutton "; closebutton. Left = 110; closebutton. Top = 40; closebutton. Width = 90; closebutton. Height = 20; closebutton. Click += new EventHandler ( closebutton_click ); this. Controls. Add ( closebutton ); questionlabel = new Label (); questionlabel. Top = 10; questionlabel. Left = 10; questionlabel. Text = "Co chcete udělat?"; this. Controls. Add ( questionlabel ); this. ClientSize = new Size (210,70); this. Text = " Formulář na nic "; void openbutton_click ( object sender, EventArgs e) new ComplexForm (). ShowDialog (); void closebutton_click ( object sender, EventArgs e) this. Close (); 29 / 60
Designer Wysiwyg editor formulářů Formulář musí být první třída deklarovaná v souboru Úpravy v designeru se projevují v kódu metoda InitializeComponent nedoporučuje se upravovat ručně! v MSVS 05 a SharpDevelop 2 je kód designeru uveden ve zvláštním souboru <formulář>.designer.cs 30 / 60
Program.cs using System ; using System. Collections. Generic ; using System. Windows. Forms ; namespace WindowsApplication static class Program [ STAThread ] static void Main () Application. EnableVisualStyles (); Application. SetCompatibleTextRenderingDefault ( false ); Application. Run ( new Form1 ()); 31 / 60
Form1.cs using System ; using System. Collections. Generic ; using System. ComponentModel ; using System. Data ; using System. Drawing ; using System. Text ; using System. Windows. Forms ; namespace WindowsApplication public partial class Form1 : Form public Form1 () InitializeComponent (); 32 / 60
Form1.Designer.cs namespace WindowsApplication partial class Form1 private System. ComponentModel. IContainer components = null ; protected override void Dispose ( bool disposing ) if ( disposing && ( components!= null )) components. Dispose (); base. Dispose ( disposing ); private void InitializeComponent () this. button1 = new System. Windows. Forms. Button (); this. SuspendLayout (); // // button1 // this. button1. Location = new System. Drawing. Point (13, 13); this. button1. Name = " button1 "; this. button1. Size = new System. Drawing. Size (75, 23); this. button1. TabIndex = 0; this. button1. Text = " button1 "; this. button1. UseVisualStyleBackColor = true ; // // Form1 // this. AutoScaleDimensions = new System. Drawing. SizeF (6F, 13F); this. AutoScaleMode = System. Windows. Forms. AutoScaleMode. Font ; this. ClientSize = new System. Drawing. Size (292, 273); this. Controls. Add ( this. button1 ); this. Name = " Form1 "; this. Text = " Form1 "; this. ResumeLayout ( false ); private System. Windows. Forms. Button button1 ; 33 / 60
Form1.cs [Design] 34 / 60
Validace vstupů Účelem validace je zamezit uživateli zadávat nepředloženosti Koncept je jednoduchý problém s křížovou kontrolou S validacemi být opatrný málo omezení obtěžuje uživatele moc omezení obtěžuje ještě víc 35 / 60
Vlastnost CauseValidation Vyvolá událost Validating u předchozí kontrolky ukázka chování... Doporučení: Nekombinovat různá nastavení CausesValidation, pokud přesně nevíte co děláte např. tlačítko Help 36 / 60
Událost Validating a Validated Událost Validating při validaci kontrolky možnost zrušit validaci e.cancel = true při zrušení validace zůstane focus na kontrolce Událost Validated při úspešné validaci 37 / 60
Jak reagovat? Příliš validace - obtěžuje uživatele zrušení validace - používat výjimečně message boxy pro každou kontrolku - používat výjimečně pozor na validaci na sobě závislých kontrolek Málo validace - obtěžuje uživatele pád programu? uložení neplatných dat? 38 / 60
Třída ErrorProvider Upozornit na chybný vstup nenásilně během zadávání Nenechat potvrdit chybně zadaná data až na konci zadávání Třída ErrorProvider umožňuje zobrazení chyby asociované s kontrolkou metoda SetError(object, string) nastaví indikaci chyby u konkrétní kontrolky zruší indikaci chyby u konkrétní kontrolky (prázdný řetězec) 39 / 60
Třída ToolTip Umožňuje rychle informovat uživatele o funkci kontrolky Jeden Tooltip funguje pro více objektů Na formuláři může být více ToolTipů Zobrazení ToolTipu propagace od nejvíc zanořené kontrolky až po kontrolku, která má tooltip definovaný Metoda SetToolTip(object, string) k objektu přiřadí popisek možnost zadat v designeru 40 / 60
Chování ToolTipu Časy InitialDelay - doba než se zobrazí (500) ReshowDelay - doba než se zobrazí jiný (100) AutoPopDelay - doba než zmizí (5000) vše v milisekundách ShowAlways určuje zda se má Tooltip zobrazovat i když kontrolka nemá focus Active zapíná/vypíná tooltipy u skupiny kontrolek 41 / 60
Menu Vhodný návrh menu dodržení standardního rozmístění Každý form může mít právě jedno hlavní menu instance třídy MainMenu přiřazuje se do property Menu 42 / 60
Položky menu Třída MenuItem společná třída pro položku menu i pro vnořená menu property Text text položky dohoda: pokud spouští dialog, zapíše se za text... Položky se přiřazují do kolekce MenuItems 43 / 60
Klávesové zkratky V MainMenu do property Text stačí přidat před příslušné písmeno znak & stiskem Alt + písmeno se příslušné menu rozbalí V MenuItem do property Text přidat před příslušné písmeno znak & do property ShortCut zapsat příslušnou klávesovou zkratku (CtrlO, F3... ) 44 / 60
Příklad MainMenu mainmenu = new MainMenu (); this. Menu = mainmenu ; MenuItem mi1 = new MenuItem ("& File "); MenuItem mi2 = new MenuItem ("& Help "); mainmenu. MenuItems. Add ( mi1 ); mainmenu. MenuItems. Add ( mi2 ); MenuItem mi3 = new MenuItem (" Open "); MenuItem mi4 = new MenuItem ("& Save... "); MenuItem mi5 = new MenuItem (" -" ); MenuItem mi6 = new MenuItem (" E& xit " ); mi6. Shortcut = Shortcut. CtrlX ; mi1. MenuItems. Add ( mi3 ); mi1. MenuItems. Add ( mi4 ); mi1. MenuItems. Add ( mi5 ); mi1. MenuItems. Add ( mi6 ); MenuItem mi7 = new MenuItem (" About... "); mi2. MenuItems. Add ( mi7 ); MenuItem mi8 = new MenuItem ("& Door... "); MenuItem mi9 = new MenuItem ("& Window... "); MenuItem mi10 = new MenuItem (" File... "); mi3. MenuItems. Add ( mi8 ); mi3. MenuItems. Add ( mi9 ); mi3. MenuItems. Add ( mi10 ); 45 / 60
Kontextové menu Třída ContextMenu funguje podobně jako MainMenu umožňuje přidávat položky MenuItem nefungují klávesové zkratky Property ContextMenu u kontrolek přiřazení kontextového menu kontrolce zobrazí se kontextové menu nejzanořenější kontrolky některé kontrolky mají vlastní kontextové menu, které je možné nahradit (např. TextBox) 46 / 60
Další vlastnosti menu Property Enabled umožnuje znepřístupnit části menu Property Checked zaškrtávací položka Property RadioCheck přepínač chování nutné dopsat ručně Property DefaultItem po dvoukliku na podmenu se spustí default položka 47 / 60
Události menu Událost Click při kliknutí na položku Událost Popup před zobrazením podmenu např. možnost vypnout některé volby Událost Select když je položka vybraná např. přeorganizování menu podle návštěvnosti 48 / 60
Co nového v.net 2.0 Nové třídy MenuStrip a ContextMenuStrip rozšiřují chování původních menu ikonky možnost dokování (i na strany) možnost nastavení směru textu možnost vkládání i jiných prvků (např. ComboBox) v designeru možnost vygenerovat standardní položky Třída ToolStripControlHost umí hostovat libovolnou kontrolku, kterou lze pak přidat do menu 49 / 60
Co nového v.net 2.0 Nové třídy MenuStrip a ContextMenuStrip rozšiřují chování původních menu ikonky možnost dokování (i na strany) možnost nastavení směru textu možnost vkládání i jiných prvků (např. ComboBox) v designeru možnost vygenerovat standardní položky Třída ToolStripControlHost umí hostovat libovolnou kontrolku, kterou lze pak přidat do menu 49 / 60
Standardní dialogy Dialogy systému windows lokalizované běžně používané (uživatel je zná) Nejsou potomci třídy Forms, ale CommonDialog spuštění metodou ShowDialog návratová hodnota DialogResult 50 / 60
ColorDialog Standardní dialog pro výběr barev Vlastnosti Color Color vybraná barva bool AllowFullOpen umožňuje vybrat uživatelské barvy 51 / 60
Open/SaveFileDialog Standardní dialog pro výběr jména souboru pro otevření/uzavření Property string FileName vybraný soubor (i při stisku tlačítka Storno) Property bool MultiSelect umožňuje výběr více souborů Property string[] FileNames pole názvů vybraných souborů při multiselect 52 / 60
Open/SaveFileDialog Property string Filter dvojice popisek maska více přípon odděleno ; např. "text (*.txt;*.rtf) *.txt;*.rtf latex (*.tex) *.tex" pokud není přípona zřejmá, je vhodné ji uvést v popisku 53 / 60
FolderBrowserDialog Standardní dialog pro výběr adresáře Property string SelectedPath vybraná cesta Property string Description popiska nad adresářovým stromem 54 / 60
FontDialog Standardní dialog pro výběr fontu Property Font Font vybraný font Property ShowColor/Effect jaká nastavení se mají zobrazit 55 / 60
PageSetupDialog Standardní dialog pro nastavení vzhledu stránky Property PrintDocument Document dokument, který se bude tisknout nutno přiřadit, jinak se při ShowDialog vyhodí výjimka 56 / 60
PrintDialog Standardní dialog pro nastavení tisku Property PrintDocument Document Property bool AllowCurrentPage/SomePage... možnost nastavení rozsahu tisku 57 / 60
PrintPreviewDialog Standardní dialog pro zobrazení náhledu tisku Property PrintDocument Document 58 / 60
Uživatelské dialogy Formulář vyvolat metodou ShowDialog Styl rámečků FixedDialog U tlačítek nastavit hodnoty DialogResult Data se předávají pomocí public vlastností 59 / 60
Konec 60 / 60