1 Používáme Visual Studio Okenní klient knihovny KvadrRovLib Založíme-si nový projekt podle obrázku. Bude se jednat o okenní aplikaci, která nám zp ř ístupní práci s naší knihovnou v p ř íjemném GUI prost ř edí. Když si prohlédneme rozhraní t ř ídy Solver, uvě domíme si, že jsme na takovouto možnost dop ř edu nemysleli (to jistě byla chyba). Solver používá pro vstupy a výstupy p ř íliš intenzivně t ř ídu System.Console. Pokusíme se situaci opravit, avšak zachovat zpě tnou kompatibilitu. S projektem NPoly vzniklo automaticky také tzv. ř ešení (solution) stejného jména. P ř idáme další nový project, jako na obrázku. Bude to knihovna t ř íd (Class Library). Jazykem knihovního projektu bude C#, ale právě prost ř ednictvím projektů mů žeme rozehrát ve VS mezijazykovou interoperabilitu. 1 1 Projekty mohou být psány v r ů zných programovacích jazycích.
Smažeme automaticky vygenerovaný soubor Class1.cs 2
a p ř idáme soubor Solver.cs, produkt naší p ř edchozí práce. 3
Rovně ž p ř ejmenujeme t ř ídu formulá ř e na FPoly, soubor s jejím kódem na FPoly.cs a nastavíme vlastnost Text t ř ídy FPoly na NPoly. 4
5 Do ř ešení mů žeme p ř idat ještě projekt konzolové aplikace, na kterém budeme testovat zpě tnou kompatibilitu. Úpravy t ídy KvadrRovLib.Solver A zač neme s úpravami t ř ídy Solver. P ř edevším je pot ř eba získat jinou možnost než nyní nepoužitelný výpis na konzolu, jak se dotázat na ř ešení rovnice. Z dů vodu jednoduchosti, protože zatím nechceme implementovat t ř ídu (typ) pro komplexní č ísla, nám postač í ř ešení jako ř etě zec. Existuje možnost, jak zajistit, aby se ř ešení spoč ítalo teprve v moment, kdy se na ně ně kdo ptá. Tuto možnost poskytují tzv. vlastnosti (property) t ř ídy. Pomocí prů vodce p ř idáme dvě nové property x1, x2. Obě budou sloužit jen pro dotazování (get). Postup pro x1 je vidě t na obrázku:
6 V kódu se objeví nové ř ádky public string x1 { get { }
7 } public string x2 { get { } } Je t ř eba naprogramovat, jakým způ sobem získáme ř etě zce ř ešení. Metodu Solve musíme modifikovat. Protože chceme zachovat kompatibilitu, p ř edeklarujeme metodu Solve na SolveInternal. A metodu Solve znovu p ř idáme, tentokrát s pomocí prů vodce (jako p ř ed chvílí, ale zvolíme Add Method): Do t ř ídy p ř idáme soukromou položku (field) sz1
8 a stejně soukromou položku sz2 typu ř etě zec. Prů vodcem p ř idáme soukromou položku valid typu bool, která bude indikovat, že ř etě zce sz1, sz2 obsahují platné ř ešení rovnice. Koneč ně pomocí prů vodce p ř idáme vlastnosti A, B, C typu double get i set, sloužící pro p ř ístup ke koeficientů m rovnice. Díky tomu, že to budou vlastnosti, mů žeme změ nit hodnotu valid na false, kdykoliv dojde ke změ ně koeficientu. P ř estaneme používat prů vodce a doprogramujeme kód. 1 namespace KvadrRovLib 2 { 3 using System; 4 5 public class Solver 6 { 7 public Solver() 8 { 9 GenerateRandom(2); 10 } 11 12 public Solver(double a, double b, double c) 13 { 14 this.a = a; 15 this.b = b; 16 this.c = c; 17 } 18 19 private double a, b, c;
20 private string sz1, sz2; 21 private bool valid = false; 22 23 public void GenerateRandom(int precission) 24 { 25 Random rand = new Random(); 26 a = Math.Round(rand.NextDouble()*10-5,precission); 27 b = Math.Round(rand.NextDouble()*10-5,precission); 28 c = Math.Round(rand.NextDouble()*10-5,precission); 29 valid = false; 30 } 31 32 private double Read(String caption) 33 { 34 Console.WriteLine(caption); 35 return double.parse(console.readline()); 36 } 37 38 /// <summary> 39 /// Only for Console Application 40 /// </summary> 41 public void Read() 42 { 43 a = Read("a:"); 44 b = Read("b:"); 45 c = Read("c:"); 46 } 47 48 private double discriminant(double a, double b, double c) 49 { 50 return b * b - 4 * a * c; 51 } 52 53 private void SolveInternal() 54 { 55 double d = discriminant(a,b,c); 56 if (d == 0) 57 { 58 sz1 = (- b / (2 * a)).tostring(); 59 sz2=sz1; 60 goto ret; 61 } 62 if (d > 0) 63 { 64 sz1 = (- b + Math.Sqrt(d) / 65 (2 * a)).tostring(); 66 sz2 = (- b - Math.Sqrt(d) / 67 (2 * a)).tostring(); 68 } 69 else 70 { 71 double r = Math.Sqrt(- d) / (2 * a); 72 if(r > 0) 73 { 74 sz1 = string.format("{0} + {1} i ", 75 - b/ (2 * a),r); 76 sz2 = string.format("{0} - {1} i ", 9
77 - b/ (2 * a),r); 78 } 79 else 80 { 81 sz1 = string.format("{0} - {1} i ", 82 - b/ (2 * a),-r); 83 sz2 = string.format("{0} + {1} i ", 84 - b/ (2 * a),-r); 85 } 86 } 87 ret: 88 valid = true; 89 } 90 91 /// <summary> 92 /// Only for Console Application 93 /// </summary> 94 public void Solve() 95 { 96 Console.WriteLine(x1); 97 Console.WriteLine(x2); 98 } 99 100 public string x1 101 { 102 get 103 { 104 if(!valid) SolveInternal(); 105 return sz1; 106 } 107 } 108 109 public string x2 110 { 111 get 112 { 113 if(!valid) SolveInternal(); 114 return sz2; 115 } 116 } 117 118 public double A 119 { 120 get 121 { 122 return a; 123 } 124 set 125 { 126 valid = false; 127 a = value; 128 } 129 } 130 131 public double B 132 { 133 get 10
11 134 { 135 return b; 136 } 137 set 138 { 139 valid = false; 140 b = value; 141 } 142 } 143 144 public double C 145 { 146 get 147 { 148 return c; 149 } 150 set 151 { 152 valid=false; 153 c = value; 154 } 155 } 156 } 157} Vytvo íme a oživíme formulá Nastavíme si záložku s formulá ř em v návrhovém pohledu (design). Není-li p ř ítomna, poklepneme na ikonu formulá ř e FPoly v prů zkumníkovi ř ešení, nebo p ř es pravé tlač ítko myši. P ř išpendlíme si Toolbox
a navrhneme formulá ř. 12
13 Na závě r nastavíme styl hranic formulá ř e nap ř. na FixedToolWindow. Než zač neme cokoliv programovat, nesmíme zapomenout si nareferencovat projekt, jehož t ř ídy hodláme používat. Je to naprosto nutné pro zda ř ilou kompilaci (odpovídá to zadání parametru /reference pro csc.exe), ale je to pot ř eba udě lat ihned p ř ed zápisem kódu. Protože od tohoto okamžiku nám mů že editor interaktivně pomáhat (technologie intellisense). Udě lá se to takto.
14 Doplníme programový kód. Č ást kódu, generovaného automaticky designérem, je vynechána. 1 using System; 2 using System.Drawing; 3 using System.Collections; 4 using System.ComponentModel; 5 using System.Windows.Forms; 6 using System.Data; 7 using KvadrRovLib; 8 9 namespace NPoly 10 { 11 /// <summary> 12 /// Summary description for Form1. 13 /// </summary> 14 public class FPoly : System.Windows.Forms.Form 15 { 16 private System.Windows.Forms.Label label1; 17 private System.Windows.Forms.TextBox textboxa; 18 private System.Windows.Forms.Label label2; 19 private System.Windows.Forms.Label label3; 20 private System.Windows.Forms.TextBox textboxx1;
21 private System.Windows.Forms.Label label4; 22 private System.Windows.Forms.TextBox textboxx2; 23 private System.Windows.Forms.Label label5; 24 private System.Windows.Forms.Button buttonsolve; 25 private System.Windows.Forms.TextBox textboxb; 26 private System.Windows.Forms.TextBox textboxc; 27 private System.Windows.Forms.Label label6; 28 private System.Windows.Forms.Button buttonrandom; 29 /// <summary> 30 /// Required designer variable. 31 /// </summary> 32 private System.ComponentModel.Container components = null; 33 34 public FPoly() 35 { 36 // 37 // Required for Windows Form Designer support 38 // 39 InitializeComponent(); 40 41 // 42 // TODO: Add any constructor code after 43 // 44 } 45 46 /// <summary> 47 /// Clean up any resources being used. 48 /// </summary> 49 protected override void Dispose( bool disposing ) 50 { 51 if( disposing ) 52 { 53 if (components!= null) 54 { 55 components.dispose(); 56 } 57 } 58 base.dispose( disposing ); 59 } 60 61 #region Windows Form Designer generated code 62 /// <summary> 63 /// Required method for Designer support - do not modify 64 /// the contents of this method with the code editor. 65 /// </summary> 66 private void InitializeComponent() 67 { 68 this.label1 = new System.Windows.Forms.Label(); 69 this.textboxa = new System.Windows.Forms.TextBox(); 70 this.textboxb = new System.Windows.Forms.TextBox(); 71 this.label2 = new System.Windows.Forms.Label(); 72 this.textboxc = new System.Windows.Forms.TextBox(); 73 this.label3 = new System.Windows.Forms.Label(); 74 this.textboxx1 = new System.Windows.Forms.TextBox(); 75 this.label4 = new System.Windows.Forms.Label(); 76 this.textboxx2 = new System.Windows.Forms.TextBox(); 77 this.label5 = new System.Windows.Forms.Label(); 15
16 78 this.buttonsolve = new System.Windows.Forms.Button(); 79 this.label6 = new System.Windows.Forms.Label(); 80 this.buttonrandom = new System.Windows.Forms.Button(); 81 this.suspendlayout(); 82 // 83 // label1 84 // 85 this.label1.location = new System.Drawing.Point(8, 48); 86 this.label1.name = "label1"; 87 this.label1.size = new System.Drawing.Size(16, 23); 88 this.label1.tabindex = 0; 89 this.label1.text = "a";... 198 // 199 // FPoly 200 // 201 this.autoscalebasesize = new System.Drawing.Size(5, 13); 202 this.clientsize = new System.Drawing.Size(280, 182); 203 this.controls.add(this.buttonrandom); 204 this.controls.add(this.label6); 205 this.controls.add(this.buttonsolve); 206 this.controls.add(this.textboxx2); 207 this.controls.add(this.textboxx1); 208 this.controls.add(this.textboxc); 209 this.controls.add(this.textboxb); 210 this.controls.add(this.textboxa); 211 this.controls.add(this.label5); 212 this.controls.add(this.label4); 213 this.controls.add(this.label3); 214 this.controls.add(this.label2); 215 this.controls.add(this.label1); 216 this.formborderstyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; 217 this.name = "FPoly"; 218 this.text = "NPoly"; 219 this.resumelayout(false); 220 221 } 222 #endregion 223 224 /// <summary> 225 /// The main entry point for the application. 226 /// </summary> 227 [STAThread] 228 static void Main() 229 { 230 Application.Run(new FPoly()); 231 } 232 233 Solver solver = new Solver(); 234 private void buttonsolve_click(object sender,
17 235 System.EventArgs e) 236 { 237 solver.a = double.parse(textboxa.text); 238 solver.b = double.parse(textboxb.text); 239 solver.c = double.parse(textboxc.text); 240 textboxx1.text = solver.x1; 241 textboxx2.text = solver.x2; 242 } 243 244 private void buttonrandom_click(object sender, 245 System.EventArgs e) 246 { 247 solver.generaterandom(1); 248 textboxa.text = solver.a.tostring(); 249 textboxb.text = solver.b.tostring(); 250 textboxc.text = solver.c.tostring(); 251 textboxx1.text = solver.x1; 252 textboxx2.text = solver.x2; 253 } 254 } 255} A takhle vypadá naše aplikace za bě hu Dokumentace ve zdrojovém kódu V C# se stejně jako v C++ používá pro jedno ř ádkový komentá ř dvojice lomítek // na zač átku a pro více ř ádkový komentá ř dvojice /* na zač áku a dvojice */ na konci. V našem kódu je však vidě t i trojice lomítek ///. Tato trojice má zvláštní význam pro automatické generování programátorské nápově dy a podpory pro intellisense. Pokud si pomocí pravého tlač ítka myši otev ř eme vlastnosti projektu a nastavíme XML dokumentač ní soubor na jmeno_assembly.xml, bude vygenerován xml soubor a dále kopírován spolu s assembly.
18 Vygenerované kvadrrovlib.xml <?xml version="1.0"?> <doc> <assembly> <name>kvadrrovlib</name> </assembly> <members> <member name="m:kvadrrovlib.solver.read"> <summary> Only for Console Application </summary> </member> <member name="m:kvadrrovlib.solver.solve"> <summary> Only for Console Application </summary> </member> </members> </doc> A tady je efekt, intellisense nám kromě deklarace metody poskytne i rozší ř enou informaci o metodě. Volání této metody má ně jaký efekt jen v konzolové aplikaci Only for Console Application.
19