2. díl - Tisk formuláře a ovládacích prvků Windows Forms

C# .NET Windows Forms 2. díl - 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 .


 

Stáhnout

Staženo 63x (634.66 kB)
Aplikace je včetně zdrojových kódů v jazyce C#

 

  Aktivity (1)

Článek pro vás napsal zpavlu
Avatar
C# a C++

Jak se ti líbí článek?
Celkem (1 hlasů) :
4444 4


 



 

 

Komentáře

Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zatím nikdo nevložil komentář - buď první!