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

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

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

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

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

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ů.


 

Stáhnout

Staženo 69x (773.96 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í!