Lekce 2 - Tisk formuláře a ovládacích prvků Windows Forms
Vítejte u druhého dílu, který vás uvede do problematiky tisku formuláře a ovládacích prvků. V dnešní lekci budeme pokračovat psaním kódu v knihovně dll (MyClass1). V prvním díle jsme definovali konstruktor takto:
public Class1(System.Windows.Forms.Control ctrl){}
Doplníme konstruktor novým kódem :
public Class1(System.Windows.Forms.Control ctrl) { this.control = ctrl; //tato kolekce slouží k vyloučení prvků z tisku deletePrintControl = new List<string>(); delegatesforControls = new List<DelegateforControls>(); //naplní kolekci prvky , které mohu tisknout AddDelegateToPrintControl("Microsoft.VisualBasic.PowerPacks.ShapeContainer", PrintShape); AddDelegateToPrintControl("System.Windows.Forms.TextBox", PrintTextBox); //další prvky které chci tisknout nutno doplnit programem na příklad: //AddDelegateToPrintControl("System.Windows.Forms.LinkLabel", PrintLinkLabel); //AddDelegateToPrintControl("System.Windows.Forms.ComboBox", PrintComboBox); //AddDelegateToPrintControl("System.Windows.Forms.CheckBox", PrintCheckBox); //AddDelegateToPrintControl("System.Windows.Forms.RadioButton", PrintRadioButton); //AddDelegateToPrintControl("System.Windows.Forms.DateTimePicker", PrintDateTimePicker); //AddDelegateToPrintControl("System.Windows.Forms.NumericUpDown", PrintNumericUpDown); //další možné ovládací prvky k tisku }
Pokud se pokusíme provést příkaz VS -> Sestavení -> Sestavit řešení, získáme následující výstup:
Sestavení: 1 úspěšně, 1 se nezdařilo, 1 aktuální, 0 přeskočeno Seznam chyb: Název PrintTextBox v aktuálním kontextu neexistuje. Název PrintShape v aktuálním kontextu neexistuje.
Toto chybové hlášení je způsobeno voláním funkcí, které nejsou zadány. Prozatím vytvoříme hlavičky požadovaných funkci takto :
//Funkce , budou provádět tisk #region "Tiskne TextBox" private void PrintTextBox(Control ctrl,ParentControlPrinting typePrint,int locationX, int locationY, out bool ScanForChildControls) { ScanForChildControls = false; }//PrintTextBox #endregion #region "Tiskne LineShape , OvalShape a RectangleShape" private void PrintShape(Control ctrl,ParentControlPrinting typePrint,int locationX, int locationY, out bool ScanForChildControls) { ScanForChildControls = false; }//print Shape #endregion
Pokud se pokusíme znovu provést příkaz VS -> Sestavení -> Sestavit řešení, bude výstup již následující:
Sestavení: 2 úspěšně, 0 se nezdařilo, 1 aktuální, 0 přeskočeno
Úprava funkce MyPrint()
V minulém dílu jsme vytvořili hlavičku funkce, která je spouštěcí funkcí pro tisk. Vylepšit tuto funkci můžeme pomocí PrintPreviewDialog, která je součástí VS.
private bool landscape = true ; private bool printPreview = true; private Rectangle RealPageSetting = new Rectangle(100, 100, 960, 600); //Velikost k tisku private Rectangle PageSettingA4 = new Rectangle(0,0, 1169, 827); // Velikost A4 v pixelech // Spuštění tisku. Výpočet výchozí polohy a orientace // Definuje objekt odešle výstup do tiskárny při tisku z aplikace model Windows Forms public void MyPrint() { using (PrintDocument pd = new PrintDocument()) { pd.DefaultPageSettings.Landscape = landscape; //Událost volána v případě potřeby výstup vytisknout aktuální stránku pd.PrintPage += PdPrintPage; //text v hlavičce formuláře pd.DocumentName = control.Text; if (printPreview) { //Představuje dialogové okno pole formuláře, který obsahuje PrintPreviewControl k tisku z aplikace model Windows Forms. using (var pp = new PrintPreviewDialog()) { if (landscape) pp.ClientSize = new Size(580, 410); else pp.ClientSize = new Size(410, 580); pp.Document = pd; pp.WindowState = FormWindowState.Normal; pp.ShowDialog(); } } else { pd.Print(); //Spustí proces tisku dokumentu. } } }
Událost PdPrintPage nám zahájí tisk formuláře a
ovládacích prvků. Nejprve musíme připravit k tisku
formulář Form1 z naší (exe) aplikace a to bez ovládacích
prvků. Provedeme přidání referencí jako v minulém dílu tentokrát ze
třídy Class1 na Class2. Průzkumník řešení -> projekt MyClass1 ->
pravé tlačítko myši -> přidat odkaz -> solution -> MyClass2. Dále
Průzkumník řešení -> projekt MyClass1 -> pravé tlačítko myši
-> přidat odkaz -> Framework -> Micr.Visual.Basic.
V generované události PdPrintPage nebudeme spouštět funkce odkazující na FormPrintDemo.Class2. Tyto funkce zpřístupníme později, jsou využívány i ovládacími prvky.
Jedná se o funkce:
FormPrintDemo.Class2.FnSetGraphics(graphics);
FormPrintDemo.Class2.FnRealPageSettingsBounds(RealPageSetting); // Reálná velikost stránky k tisku
FormPrintDemo.Class2.FnDrawBachgRoundImage(control.BackgroundImage, control.BackgroundImageLayout, RealPageSetting);
Výsledná funkce bude vypadat:
private void PdPrintPage(object sender, PrintPageEventArgs ev) { graphics = ev.Graphics; // FormPrintDemo.Class2.FnSetGraphics(graphics); //reálná velikost stránky k tisku // FormPrintDemo.Class2.FnRealPageSettingsBounds(RealPageSetting); graphics.Clip = new Region(PageSettingA4); //barva formuláře Form using (SolidBrush brush = new SolidBrush(control.BackColor)) graphics.FillRectangle(brush, RealPageSetting); //Image pozadí formuláře //FormPrintDemo.Class2.FnDrawBachgRoundImage(control.BackgroundImage, control.BackgroundImageLayout, RealPageSetting); //vykreslí platné ohraničení stránky pro návrh if (Ohraniceni) { using (Pen pen = new Pen(Color.Red)) graphics.DrawRectangle(pen, RealPageSetting); Rectangle rec = Rectangle.Inflate(PageSettingA4, -2, -2); using (Pen pena = new Pen(Color.Black)) graphics.DrawRectangle(pena, rec); } graphics.ResetClip(); //tisk nadpisu formuláře , velikost písma , podtržení písma if (!String.IsNullOrEmpty(control.Text)) { using (StringFormat sf = new StringFormat()) { sf.LineAlignment = StringAlignment.Near; sf.Alignment = StringAlignment.Center; using (SolidBrush brush = new SolidBrush(Color.Black)) graphics.DrawString(control.Text, control.Font, brush, RealPageSetting, sf); } } PrintControls(control, RealPageSetting.X, RealPageSetting.Y ) ; //Nebudou vytištěny další stránky ev.HasMorePages = false; }
Volaná funkce PrintControls(control, RealPageSetting.X, RealPageSetting.Y ); bude připravovat k tisku ovládací prvky a bude volaná rekurzí. Vytvoříme hlavičku této funkce a provedeme sestavení našich projektů.
private void PrintControls(System.Windows.Forms.Control ctrl, int x0, int y0){}
V okně Výstup:
Sestavení bylo úspěšně dokončeno. Sestavení: 2 úspěšně, 0 se nezdařilo, 1 aktuální, 0 přeskočeno.
Malé odbočení
Každý ovládací prvek je třída. Na formulář můžeme ovládací prvek přetáhnout pomocí VS -> panel nástrojů nebo programově.
//programově using System.Collections.Generic; public partial class Form1 : Form { private static TextBox tb = new TextBox(); //vytvoří text box private List<TextBox> tbp = new List<TextBox>(3){tb,tb,tb};//nebo pole TextBoxu }
Rozdíl je ve vytváření prvků z doplňků balíčku Visual Basic.
using Microsoft.VisualBasic.PowerPacks; using mvb = Microsoft.VisualBasic.PowerPacks; public partial class Form1 : Form { private mvb.ShapeContainer mShape = new mvb.ShapeContainer(); private mvb.LineShape line1 = new mvb.LineShape(); private mvb.LineShape line2 = new mvb.LineShape(); private mvb.OvalShape oval1 = new OvalShape(); //konstruktor shapeContainer.Parent = this; line1.Parent = shapeContainer; line2.Parent = shapeContainer; oval1.Parent = shapeContainer; }
Z těchto důvodů je dekódování tisku rozdílné.
Trochu teorie a použitých názvů
Pokud se podíváme na hotovou konstrukci třídy Class1, jedná se o
návrhový vzor továrny na objekty.
Co jsou návrhové vzory?
Návrhový vzor je způsob postupu, dle kterého upravíme náš postup při
tvorbě programu.
Výhody tovární metody:
- Skrývá složitost tvorby od spotřebitele.
- Zajišťuje, že logika vytvoření objektu bude na jednom místě.
- Pomáhá přizpůsobit tvorbu, aniž byste rušili logiku spotřebitele.
- Přináší logické oddělení tvorby a použití.
Rekurze
Rekurzi používáme když nějaká metoda volá sama sebe. Uvedu jednoduchý příklad výpočtu faktoriálu .
private long Faktorial(int x) { if(x==0) return 1; else return x*Faktorial(x-1); }
Názvy
- Kontejner v našem případě kolekce, do které budeme vkládat ovládací prvky.
- Rodič je náš formulář, dítě ovládací prvek nakreslený na našem formuláři.
- Pokud ovládací prvek je kontejnerem pro další ovládací prvky, pak formulář je prarodič, na něm nakreslený ovládací prvek je rodič a nejvýše položený nakreslený prvek je dítě.
Pokračování v příštím díle .
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 96x (634.66 kB)
Aplikace je včetně zdrojových kódů v jazyce C#