Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
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 3 - Tisk formuláře a ovládacích prvků Windows Forms

V minulém díle jsme končili s trochu teorie a použitých názvů. Připravíme si naši knihovnu C++/CLR:safe pro pokračování. V tabulce je ukázka vlivu přepínače C++/CLR na možnosti programátora. Zde nebudu vysvětlovat jednotlivé možnosti, jsou dostatečně popsané na webu.

Možnosti přepínače CLR - Tisk celých formulářů ve Windows Forms

Příprava (dll) knihovny Class2

Ve VS otevřeme průzkumník řešení a myší najedeme na MyClass2. Pravé tlačítko myši otevřeme vlastnosti. Tlačítkem Add.New Reference... přidáme Microsoft.Visu­alBasic.Power­.Packs.Stejně přidáme i System.Window­s.Forms a přidáme System.Drawing, viz obrázek.

Vlastnosti konfigurace v C# .NET - Tisk celých formulářů ve Windows Forms

Znovu přejdeme na Stránky vlastností MyClass2 a přejdeme na Vlastnosti Konfigurace a v poli
Common Language Runtime Support naklikneme: Safe MSIL Common Language Runtime Support (/clr:safe). Stránky vlastností MyClass2 musí být nastaveny v Konfiguraci na Všechny konfigurace. Funkce FnSetGrap­hics(Graphics^ gr) a FnRealPa­geSettingsBou­nds(Rectangle RealPageSetting) jsou statické. To znamená, že je pouze jedna instance této funkce bez ohledu kolikrát je třída použita.

Znovu přikládám obrázek.

Vlastnosti konfigurace - Tisk celých formulářů ve Windows Forms

V průzkumníku řešení vidíme, že máme Header Files - MyClass2.h a Source Files - MyClass2.cpp.
Zde doporučuji psát kód programu do obou, není to sice nutné, při větším projektu ztratíte přehled a váš program bude špatně čitelný. Do Header souboru zapisujeme pouze hlavičky funkcí.

Programujeme v knihovně MyClass2

Přejdeme do knihovny MyClass1 na funkci PdPrintPage(....), zrušíme komentář u FnSetGraphics(grap­hics), zkopírujeme tuto funkci do schránky, otevřeme MyClass2 a vložíme do Class2.

Upravíme hlavičkový soubor:

#pragma once  //hlavička může být načtena pouze 1x velmi důležité

namespace FormPrintDemo {

    public ref class Class2 //v C# -> public class Class2
    {
    public:
        Class2(); //konstruktor
        void static FnSetGraphics(Graphics^ gr); //hlavička funkce

    private:
        Graphics^ graphics;
    };
}//namespace

Upravíme Source soubor MyClass2.cpp

#include "stdafx.h"
#include "MyClass2.h"

namespace FormPrintDemo {

    Class2::Class2(){};

    void  Class2::FnSetGraphics(Graphics^ gr)
    {
        graphics = gr;  //tělo funkce
    };
}

Doplníme reference na knihovny v Stdafx.h, budou se kompilovat pouze 1x.

#pragma once

#using <System.dll>
#using <System.Windows.Forms.dll>

using namespace System;
using namespace System::Drawing;
using namespace System::Windows::Forms;
using namespace Microsoft::VisualBasic::PowerPacks;
using namespace System::Drawing::Drawing2D;

namespace sd = System::Drawing ;
namespace swf = System::Windows::Forms;
namespace sri = System::Runtime::InteropServices;

Stejný postup bude u funkce FnRealPageSet­tingsBounds(Re­alPageSetting); a také u funkce
FnDrawBachgRou­ndImage(control­.BackgroundIma­ge,control.Bac­kgroundImageLa­yout,RealPage­Setting);. Vytvoříme další hlavičkový a source soubor MyClassImage.h a MyClassImage.cpp. Hlavičkový soubor MyClass2.h bude vypadat takto:

#pragma once
#include "MyClassImage.h"

namespace FormPrintDemo {

    public ref class Class2 : MyClassImage  //Class2 dědí z MyClassImage
    {
    public:
        Class2();
    void static FnSetGraphics(Graphics^ gr);
        void static FnRealPageSettingsBounds(Rectangle RealPageSetting);
        void static FnDrawBachgRoundImage(Image ^image, swf::ImageLayout imagelayout, Rectangle rec );

    private:
        static Graphics^ graphics;
        static Rectangle realPageSetting;
    };
}

Source soubor MyClass2.cpp:

#include "stdafx.h"
#include "MyClass2.h"

namespace FormPrintDemo {

    Class2::Class2(){}; //konstruktor

    void  Class2::FnSetGraphics(Graphics^ gr)
    {
        graphics = gr;
    };

    void Class2::FnRealPageSettingsBounds(Rectangle RealPageSetting)
    {
        realPageSetting = RealPageSetting;
    };

    void Class2::FnDrawBachgRoundImage(Image ^image, swf::ImageLayout imagelayout, Rectangle rec )
    {
        if(image == nullptr){return;} //v C# -> null
        DrawBachgRoundImageA(graphics, image, rec, imagelayout );
    };
}//namespace

Obrázek na pozadí pro ovládací prvek

Upravíme soubor MyClassImage.h

#pragma once

namespace FormPrintDemo {

    public ref class MyClassImage
    {
    protected :
        void DrawBachgRoundImageA(Graphics^ gr, Image^ image, Rectangle rec, swf::ImageLayout layout );

    private:
        Brush^ DrawBachgRoundImage(Graphics^ gr, Image^ image, Rectangle rec, swf::ImageLayout layout);
        Image^ backgroundImage;
        ImageLayout imageLayout;
        Image ^image ;
    };
}

Upravíme soubor MyClassImage.cpp

#include "stdafx.h"
#include "MyClassImage.h"

namespace FormPrintDemo {

    void MyClassImage::DrawBachgRoundImageA(Graphics^ gr, Image^ image, Rectangle rec, swf::ImageLayout layout)
    {
        Brush ^imageBrush = DrawBachgRoundImage(gr , image , rec , layout);
    if (imageBrush != nullptr)
    {
      gr->FillRectangle(imageBrush, rec);
          delete imageBrush;
        }
    }//DrawBachgRoundImageA

    Brush^ MyClassImage::DrawBachgRoundImage(Graphics^ graphics, Image^ image, Rectangle rec, swf::ImageLayout layout)
    {
            this->backgroundImage = (Image^) image ;
            TextureBrush ^textureBrush = safe_cast<TextureBrush^>(nullptr);

            if (this->backgroundImage != nullptr)
        {
        double num1 = safe_cast<double>(rec.X);
        double num2 = safe_cast<double>(rec.Y);
                int num3 = 0;
                int num4 = 0;
        Image ^image = this->backgroundImage;
        WrapMode wrapMode = WrapMode::Clamp;
        Bitmap ^bitmap = safe_cast<Bitmap^>(nullptr);
                this->imageLayout = layout;
                switch (this->imageLayout)
        {
                case ImageLayout::Tile:
                    wrapMode = WrapMode::Tile;
                    break;

                case ImageLayout::Center:
                    num3 = rec.Width - this->backgroundImage->Width;
                    if (num3 > 0)
                        num1 = safe_cast<double>(rec.X) + safe_cast<double>(num3) / 2.0;
                    num4 = rec.Height - this->backgroundImage->Height;
                    if (num4 > 0)
                    {
                        num2 = safe_cast<double>(rec.Y) + safe_cast<double>(num4) / 2.0;
                        break;
                    }
                    else
                    break;

                case ImageLayout::Stretch:
                    bitmap = gcnew Bitmap(rec.Width, rec.Height);
                    graphics = Graphics::FromImage(safe_cast<Image^>(bitmap));
                    graphics->DrawImage(image, 0, 0, bitmap->Width, bitmap->Height);
                            delete graphics;
                    break;

                case ImageLayout::Zoom:

                    double num5 = (double)(rec.Width) / safe_cast<double>(image->Width);
                    double num6 = (double)(rec.Height) / (double)(image->Height);
                    if (num5 > num6)
                    {
                        num1 = (double)rec.X + (num5 - num6) * (double)(image->Width) / 2.0;
                        bitmap = gcnew Bitmap(int)(Math::Round(double)(image->Width) * num6)), rec.Height);
                    }
                    else
                    {
                        num2 = safe_cast<double>(rec.Y) + (num6 - num5) * safe_cast<double>
 (image->Height) / 2.0;
                        bitmap = gcnew Bitmap(rec.Width,safe_cast<int(Math::Round(safe_cast<double>(image->Height) * num5)));
                    }
                    graphics = Graphics::FromImage(safe_cast<Image^>(bitmap));
                    graphics->DrawImage(image, 0, 0, bitmap->Width, bitmap->Height);
                            delete graphics;
                    break;
            }//switch

            if (bitmap != nullptr)
            {
                textureBrush = gcnew TextureBrush(safe_cast<Image^>(bitmap), wrapMode);
                delete bitmap;
            }
            else
            textureBrush = gcnew TextureBrush(image, wrapMode);
            Matrix ^transform = textureBrush->Transform;
            transform->Translate(safe_cast<float>(num1), safe_cast<float>(num2));
            textureBrush->Transform = transform;
            }
            return safe_cast<Brush^>(textureBrush);
    }
}

Poslední úprava před testem bude v Class1 v PdPrintPage(......) takto :

//Image pozadí formuláře (volaná funkce není statická)
FormPrintDemo.Class2 class2 = new Class2();
class2.FnDrawBachgRoundImage(control.BackgroundImage, control.BackgroundImageLayout, RealPageSetting);

Provedeme sestavení, pokud jsme programovali bezchybně:

Sestavení bylo úspěšně dokončeno.
Nové sestavení všeho: 3 úspěšně, 0 se nezdařilo, 0 přeskočeno

Test formuláře

Formulář nyní ozkoušíme:

  • Můžeme měnit barvu pozadí formuláře
  • Můžeme zadat Image pozadí (BackgroundImage)
  • Můžeme měnit rozložení obrázku pozadí (BackgroundIma­geLayout -> None, Tile, Center, Zoom, Stretch)
  • Můžeme zapnou nebo vypnout zobrazení ohraničení na stránce
Test tisku v C# .NET - Tisk celých formulářů ve Windows Forms

Není možné vysvětlovat činnost kódu FnDrawBachgRou­ndImage(.....), rozbor kódu by zabral samostatný výklad. Pokračování v příštím díle, kde bude rozebrána logika výběru ovládacích prvků.


 

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 97x (773.96 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