IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

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í PrintPreviewDi­alog, 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(con­trol, 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:

  1. Skrývá složitost tvorby od spotřebitele.
  2. Zajišťuje, že logika vytvoření objektu bude na jednom místě.
  3. Pomáhá přizpůsobit tvorbu, aniž byste rušili logiku spotřebitele.
  4. 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#

 

Předchozí článek
Tisk formuláře a ovládacích prvků Windows Forms
Všechny články v sekci
Tisk celých formulářů ve Windows Forms
Přeskočit článek
(nedoporučujeme)
Tisk formuláře a ovládacích prvků Windows Forms
Článek pro vás napsal zpavlu
Avatar
Uživatelské hodnocení:
3 hlasů
C# , C++ a assembler
Aktivity