[[pw:draw5]]
 

Jednoduchý kreslící program - dialog s parametry barevné výplně

BrushManipulator

Vytvoříme pomocnou třídu, kterou zobrazíme v propertyGridu

V Solution Exploreru pravou myší klikneme na projekt Draw
Z kontextového menu vybereme Add, Class
Soubor pojmenujeme BrushManipulator.cs

Před class připíšeme public, aby třída byla dostupná i z jiných jmenných prostorů

Deklarujeme vlastnost Color1

        public Color Color1 { get; set; }
  • Není to proměnná v deklaraci jsou navíc { }
  • Není to funkce v deklaraci nejsou ( )
  • Vlastnost (property) představuje dvojici funkcí pro čtení a zápis hodnoty, ale v programu s ní pracujeme jako s porměnnou
  • Nejjednodušší implemenace { get; set; } vytvoří skrytou proměnnou a dvě funkce pro čtení a změmu proměnné
  • PropertyGrid zobrazuje právě vlastnosti, proto vlastnost programujeme
        [Category ("Colors")]
        [DisplayName ("FirstColor")]
        [Description ("First Color ...")]
        public Color Color1 { get; set; }

Vlastnosti můžeme přidat attributy, které překladač uloží spolu s dalšími typovými informacemi do přeloženého programu.
Attributy se vztahují k dané deklaraci (může to být i deklarace proměnné, funkce nebo třídy

Category ovlivní rozdělení vlastností do skupin v PropertyGrid
DisplayName nahradí identikátor Color1 ve vzniklé tabulce

Podobně přidáme Color2 a celočíselné vlastnosti X1, Y1, X2 a Y2,

Doplníme konstruktor s dvěmi barvami zadanými jako parametry

        public BrushManipulator (Color first, Color second) { ... }

A funkci createBrush, která ze zdadaných vlastností vytvoří štětec

        public LinearGradientBrush createBrush ()
        {
            return new LinearGradientBrush (new PointF (X1, Y1),
                                            new PointF (X2, Y2),
                                            Color1,
                                            Color2);
        }

Celá třída BrushManipulator

using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
 
namespace Draw
{
    public class BrushManipulator
    {
        public BrushManipulator (Color first, Color second)
        {
            Color1 = first;
            Color2 = second;
 
            X1 = 0;
            Y1 = 0;
 
            X2 = 100;
            Y2 = 100;
        }
 
        public LinearGradientBrush createBrush ()
        {
            return new LinearGradientBrush (new PointF (X1, Y1),
                                            new PointF (X2, Y2),
                                            Color1,
                                            Color2);
        }
 
        [Category ("Colors")]
        [DisplayName ("FirstColor")]
        [Description ("First Color ...")]
        public Color Color1 { get; set; }
 
        [Category ("Colors")]
        [DisplayName ("SecondColor")]
        [Description ("Second Color ...")]
        public Color Color2 { get; set; }
 
        [Category ("From")]
        public int X1 { get; set; }
 
        [Category ("From")]
        public int Y1 { get; set; }
 
        [Category ("To")]
        public int X2 { get; set; }
 
        [Category ("To")]
        public int Y2 { get; set; }
 
    }
}

BrushManipulator.cs

Úpravy hlavního okna DrawForm

Proměnné brush a brushColor nahradíme proměnnou manipulator

        private BrushManipulator manipulator;

V konstruktoru manipulator vytvoříme

            pen = new Pen (colorTools[0].BackColor); // modra barva podle prvniho panelu
 
            manipulator = new BrushManipulator (colorTools[1].BackColor, // zluta podle druheho panelu
                                                colorTools[2].BackColor); // cervena podle tretiho panelu

V metodě pictureBox_MouseMove pomocí manipulátoru vytvoříme štětec a uložíme ho do lokální proměnné

        private void pictureBox_MouseMove (object sender, MouseEventArgs e)
        {
            if (press)
            {
                Graphics g = Graphics.FromImage (pictureBox.Image);
                g.DrawImage (save, 0, 0);
 
                Brush brush = manipulator.createBrush ();

Ve funkci colorPanel_MouseDown, pokud klikneme pravou myší na barevný panel, změníme obě barvy manipulátoru na stejnou barvu.

        private void colorPanel_MouseDown (object sender, MouseEventArgs e)
        {
            Panel panel = sender as Panel;
            // Panel panel = (Panel) sender;
 
            if (e.Button == MouseButtons.Left && Control.ModifierKeys != Keys.Shift)
            {
                pen.Color = panel.BackColor;
                refreshPen ();
            }
            else if (e.Button == MouseButtons.Right)
            {
                manipulator.Color1 = panel.BackColor;
                manipulator.Color2 = panel.BackColor; // !? jednobarevny stetec
                refreshBrush ();
            }
            else if (e.Button == MouseButtons.Middle || e.Button == MouseButtons.Left && Control.ModifierKeys == Keys.Shift)
            {
                colorDialog.Color = panel.BackColor;
                if (colorDialog.ShowDialog () == DialogResult.OK)
                {
                    panel.BackColor = colorDialog.Color;
                    pen.Color = panel.BackColor;
                    refreshPen ();
                }
            }
        }

DrawForm.cs

Reakce na změnu tužky

Parametry tužky a štetce budeme zobrazovat v dialogových oknech. Šířka tužky se navíc zobrazuje v horním toolPanelu. Pokud změníme parametry tužky nebo štetce, chceme parametry také znovu zobrazit.

Vytvoříme událost informující různé části programu o změně tužky

Delegát připomíná deklaraci funkce a uvedeme v něm parametr typu Pen.

        public delegate void PenHandler (Pen p);

Událost pojmenujeme penChanged a bude obsahovat posloubnost funkcí (s halvičkami dle předchozí deklarace), které se mají zavolat

        public event PenHandler penChanged;

Funkce refreshPen jednotlivé funkce zavolá

        public void refreshPen ()
        {
            if (penChanged != null)
                penChanged (pen);
        }

V konstruktoru pak do seznamu funkcí přidáme metodu updatePenWidth

            penChanged += updatePenWidth;

refreshPen zavolá všechny funkce z posloupnosti, updatePenWidth zobrazí šířku tužky v horní částsti okna

        private void updatePenWidth (Pen p)
        {
            penWidthNumeric.Value = (int) p.Width;
        }

Ve funkci penMenuItem_Click přidáme metodu dialogu setPen do seznamu funkcí, které se mají zavolat

        private void penMenuItem_Click (object sender, EventArgs e)
        {
            PenDialog dlg = new PenDialog ();
            dlg.setPen (pen);
            penChanged += dlg.setPen;  // dialog bude informovan o zmenach
            dlg.form = this; // dialog bude pomoci form.refreshPen informovat o zmenach
            dlg.Show ();
        }

A dialogovému oknu předáme odkaz na hlavní okno.
Pokocí form.refreshPen () dialog oznámí hlavnímu oknu, že změnil tužku

V PenDialogu v “design režimu” vybereme propertyGrid, v Poperties přejdeme na událostmi klikneme na PropertyValueChanged a vznikne funkce propertyGrid_PropertyValueChanged

Pokud tedy v dialogovém boxu změníme vlastnosti tužky, zavoláme refreshPen v hlavním okně.

A naopak, pokud někdo zavolá refreshPen, je zavolána metoda setPen, ktrá v tabulce zobrazí nový objekt.

Zdrojový text dialogového okna

    public partial class PenDialog : Form
    {
        public PenDialog ()
        {
            InitializeComponent ();
        }
 
        public void setPen (Pen p)
        {
            propertyGrid.SelectedObject = p;
        }
 
        public DrawForm form;
 
        private void propertyGrid_PropertyValueChanged (object s, PropertyValueChangedEventArgs e)
        {
            if (form != null)
                form.refreshPen ();
        }
    }

PenDialog.cs

Reakce na změnu štětce

Obdobobně pro štětec v DrawForm.cs deklarujeme typ pro jednotlivé funkce a proměnnou obsahující seznam funkcí, které chceme zavolat při změně štětce

        public delegate void BrushHandler (BrushManipulator b);
        public event BrushHandler brushChanged;

( Přesněji: posloupnost neobsahuje obyčejné funkce, ale dvojice objekt a jeho metoda. )

Metoda, která zavolá funkce z uložené posloupnosti

        public void refreshBrush ()
        {
            if (brushChanged != null)
                brushChanged (manipulator);
        }

Vrátíme se do “designu” hlavního okna DrawForm
Do “Edit” menu přidáme položku ”&Brush Properties”, pojmenujeme ji brushMenuItem

Dvakrát kliknenme na novou položku menu (třídu BrushDialog ještě nemáme)

        private void brushMenuItem_Click (object sender, EventArgs e)
        {
            BrushDialog dlg = new BrushDialog ();
            dlg.setBrushManipulator (manipulator);
            brushChanged += dlg.setBrushManipulator;
            dlg.form = this; 
            dlg.Show ();
        }

BrushDialog

Podobně jako v minulé kapitole

V Solution Exploreru pravou myší klikneme na projekt Draw
Z kontextového menu vybereme Add, Form (Windows Forms)
Soubor pojmenujeme BrushDialog.cs

  • Do vzniklého okna přidáme z Toolbox ze skupiny All Windows Forms prvek PropertyGrid
  • přejmenujeme na propertyGrid
  • nastavíme Dock na Fill
  • mezi událostmi klikneme na PropertyValueChanged a vznikne funkce propertyGrid_PropertyValueChanged

BrushDialog v propertyGridu zobrazuje parametry BrushManipulátoru

    public partial class BrushDialog : Form
    {
        public BrushDialog ()
        {
            InitializeComponent ();
        }
 
        public void setBrushManipulator (BrushManipulator b)
        {
            propertyGrid.SelectedObject = b;
        }
 
        public DrawForm form;
 
        private void propertyGrid_PropertyValueChanged (object s, PropertyValueChangedEventArgs e)
        {
            if (form != null)
                form.refreshBrush ();
        }
    }

BrushDialog.cs

 
pw/draw5.txt · Last modified: 2020/11/10 19:19 by 88.103.111.44
 
Recent changes RSS feed Creative Commons License Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki