V programu z minulého týdnu jsem upravil třídu Area tak,
aby zadanému panelu přidala kód pro pohyb pomocí myši
Třídy pro jednotlivé panely jsou ozdvozené ze třídy UserControl
( Když byly odvozené ze třídy Area,
která někdy ještě nemusela být přeložena,
tak VisualStudio nemohlo zobrazit panel v “design” režimu. )
Nyní třídy pro jednotlivé panely v konstruktoru zavolají new Area (this);
třída Area připojí své metody jako reakci na pohyb myši nad příslušným panelem.
Pohyb panelu pomocí levého tlačítka myši
a zvětšování pomocí prostředního tlačítka
u některých panelů funguje jen na barevném okraji panelu,
uvnitř je umístěn jiný grafický prvek jako např. takulka s daty.
Samotná třída Area není odvozena z vizuálního prvku.
public class Area { private Control control; public Area (Control control0) { control = control0; control.MouseDown += Area_MouseDown; control.MouseMove += Area_MouseMove; control.MouseUp += Area_MouseUp; } private int X0, Y0; private bool press = false; private void Area_MouseDown (object sender, MouseEventArgs e) { X0 = e.X; Y0 = e.Y; press = true; } private void Area_MouseMove (object sender, MouseEventArgs e) { if (press) { if (e.Button == MouseButtons.Left) { control.Left += e.X - X0; control.Top += e.Y - Y0; } else if (e.Button == MouseButtons.Middle) { control.Width += e.X - X0; control.Height += e.Y - Y0; X0 = e.X; Y0 = e.Y; } } } private void Area_MouseUp (object sender, MouseEventArgs e) { press = false; } }
Původní kód z kapitoly o pohyblivých panelech jsem přemístil do třídy ImageArea odvozené ze třídy UserControl.
public partial class ImageArea : UserControl { public ImageArea (string path = "") { InitializeComponent (); new Area (this); if (path != "") BackgroundImage = new Bitmap (path); } private void colorMenuItem_Click (object sender, EventArgs e) { colorDialog.Color = this.BackColor; if (colorDialog.ShowDialog () == DialogResult.OK) BackColor = colorDialog.Color; } private void imageMenuItem_Click (object sender, EventArgs e) { if (openDialog.ShowDialog () == DialogResult.OK) { BackgroundImage = new Bitmap (openDialog.FileName); } } private void borderMenuItem_Click (object sender, EventArgs e) { borderMenuItem.Checked = ! borderMenuItem.Checked; if (borderMenuItem.Checked) BorderStyle = BorderStyle.FixedSingle; else BorderStyle = BorderStyle.None; } private void stretchMenuItem_Click (object sender, EventArgs e) { stretchMenuItem.Checked = ! stretchMenuItem.Checked; if (stretchMenuItem.Checked) BackgroundImageLayout = ImageLayout.Stretch; else BackgroundImageLayout = ImageLayout.None; } }
Třída HtmlArea obsahuje komponentu typu WebBrowser umístěnou na celé ploše panelu.
Konstruktor má jako parametr cestu k html souboru, který v panelu zobrazí.
WebBrowser cestu k souboru dostane jak typ Uri, kde uvedeme file: a zpětná lomítka nahradíme obyčejnými lomítky.
Panelu ještě přídáme vlastnost Browser, která dovoluje pouze číst odkaz na komponentu webBrowser a nedovoluje zápis.
Vlastnost se objeví v tabulce PropertyGrid mezi vlastnostmi panelu v oddělení Data
public partial class HtmlArea : UserControl { public HtmlArea (string path) { InitializeComponent (); new Area (this); webBrowser.Url = new Uri ("file:///" + path.Replace ('\\', '/').Replace("//", "/")); } [ Category ("Data") ] public WebBrowser Browser { get => webBrowser; } }
Podobně třída TextArea obsahuje TextBox zobrazujícíobsah textového souboru.
V konstruktoru funkce File.ReadAllText přečte obsah celého souboru a výsledkem je jeden řetězec znaků.
Vlastnost TextBox poskytuje odkaz na textovou komponentu, jen je funkce get zapsána trochu jinak, než v předchozím odstavci.
public partial class TextArea : UserControl { public TextArea (string path) { InitializeComponent (); new Area (this); textBox.Text = File.ReadAllText (path); } [Category ("Data")] public TextBox Editor { get { return textBox; } } }
V tomto panelu se o zobrazení postará komponenta grid typu DataGridView
V konstruktoru se pokusíme přečíst soubor obsthující data oddělená čárkami (.csv)
List< List < string > > complete = new List < List < string > > ();
foreach (string line in lines) { List<string> data = new List<string> (); foreach (string item in line.Split (',')) { data.Add (item); } int cnt = data.Count; if (cnt > columns) columns = cnt; complete.Add (data); }
grid.ColumnCount = columns; foreach (var data in complete) grid.Rows.Add (data.ToArray());
Celý panel zobrazující tabulku dat
public TableArea (string path) { InitializeComponent (); string [] lines = File.ReadAllLines (path); int columns = 0; List< List < string > > complete = new List < List < string > > (); foreach (string line in lines) { List<string> data = new List<string> (); foreach (string item in line.Split (',')) { data.Add (item); } int cnt = data.Count; if (cnt > columns) columns = cnt; complete.Add (data); } grid.ColumnCount = columns; foreach (var data in complete) grid.Rows.Add (data.ToArray()); } [ Category ("Data") ] public DataGridView Table { get => grid; } }
Grafy zobrazí komponenta chart typu Chart
Na webu jsem nalezl krátký příklad jak zobrazit sloupcový graf se třemi hodnotami
// http://csharpexamples.com/c-chart-control-example/ chart.Series.Clear (); chart.Titles.Add (""); Series data = chart.Series.Add ("first"); data.Points.Add (10); data = chart.Series.Add ("second"); data.Points.Add (20); data = chart.Series.Add ("third"); data.Points.Add (30);
Nebo kruhový diagram
// https://stackoverflow.com/questions/34104484/how-to-build-a-pie-chart-based-on-int-values chart.Series.Clear (); Series data = chart.Series.Add (""); data.ChartType = SeriesChartType.Pie; data.Points.AddXY ("first", 10); data.Points.AddXY ("second", 20); data.Points.AddXY ("third", 30);
public partial class ChartArea : UserControl { public ChartArea (string path) { InitializeComponent (); new Area (this); chart.Series.Clear (); Series data = chart.Series.Add (""); string[] lines = File.ReadAllLines (path); foreach (string line in lines) { string [] items = line.Split (','); int cnt = items.Length; string value = (cnt >= 1) ? items[0] : ""; string name = (cnt >= 2) ? items[1] : ""; int number = 0; int.TryParse (value, out number); data.Points.AddXY (name, number); } } [ Category ("Data")] public Chart Chart { get => chart; } }