[[pw:draw]]
 

Jednoduchý kreslící program

https://gitlab.fjfi.cvut.cz/culikzde/pw

Opět vytvoříme nový projekt Menu File / New / Project
Vybereme typ projektu Windows Forms App (.NET Framework) C#
Projekt nazveme Draw

Z toolboxu, ze skupiny Containers, přidáme Panel

  • v Properties nastavíme (name) na toolPanel (s malým písmenem na začátku)
  • Dock nastavíme na Top, panel se umístí k hornímu okraji okna
  • můžeme BorderStyle nastavit na FixedSingle, aby okraje panelu byly vidět

Z toolboxu, ze skupiny Common, přidáme PictureBox

  • nastavíme (name) na pictureBox (s malým písmenem na začátku, PictureBox s velkým písmenem je jméno třídy)
  • Dock nastavíme na Fill, box zaplní vnitřek okna

V Solution Exploreru pravou myší klikneme na původní Form1.cs, z kontextového menu vybereme Rename a
přejmenujeme na DrawForm (podívejte se na zelený obdélníček na následujícím obrázku)

Zkontrolujeme, zda pictureBox nepřekrývá toolPanel (zkontrolujte roh označený žlutým kroužkem)

Pokud překrývá, v hlavním menu View / Other windows / Document Outline nebo Ctrl+Alt+T
Na levé záložce Document Outline, posuneme myší pictureBox nad toolPanel

Klikneme na pictureBox,
v Properties přepneme na Events (tlačítko s bleskem),
a dvakrát klikneme do prázdného políčka vpravo od MouseDown,
zobrazí se nám metoda pictureBox_mouseDown.

        private void pictureBox_MouseDown(object sender, MouseEventArgs e)
        {
 
        }

:!: Hlavičku metody sami nepište, vždy “naklikejte”, chyběla by vazba v DrawForm.designer.cs.

Doplníme několik příkazů:

        public DrawForm ()
        {
            InitializeComponent ();
            pictureBox.Image = new Bitmap (800, 600);
        }
 
        private void pictureBox_MouseDown(object sender, MouseEventArgs e)
        {
            Graphics g = Graphics.FromImage (pictureBox.Image);
            Pen pen = new Pen (Color.Red);
            g.DrawLine (pen, 0, 0, e.X, e.Y);
            pictureBox.Invalidate ();
        }

pictureBox je jen “rámeček” držící vlastní obrázek v pictureBox.Image
V konstruktoru sem umístíme novou “Bitmapu” - obddélníkové pole barevných bodů

            pictureBox.Image = new Bitmap (800, 600);

Při stisku myši na chvilku vytvoříme objekt typu Graphics, s jehož pomocí budeme kreslit do bitmapy.
( Na konci funkce, zanikne lokální proměnná g a na objekt typu Graphics jižnepovede ukazatel a objekt zanikne. )

Připravíme si červenou “tužku” na následující kreslení.

Nakreslíme červenou čáru z levého horního rohu 0,0 na místo stisku myši e.X,e.Y

Funkcí Invalidate upozorníme Windows, že mají překreslit náš pictureBox

            Graphics g = Graphics.FromImage (pictureBox.Image);
            Pen pen = new Pen (Color.Red);
            g.DrawLine (pen, 0, 0, e.X, e.Y);
            pictureBox.Invalidate ();

na gitlab.fjfi.cvut.cz naleznete zdrojový text právě z tohoto okamžiku

Kreslíme úsečku

Nyní chceme nakreslit úsečku od místa stisknutí myši až po místo, kde myš uvolníme.

Připravíme si proměnné X0 a Y0 pro uložení souřadnice kde byla myš stisknuta.
Proměnné nebudou lokální, ale budou na úrovni třídy DrawForm, aby existovaly mezi jednotlivými voláními funkcí pictureBox_mouseDown a pictureBox_mouseUp

pictureBoxu přidáme (“naklikáme”) událost MouseUp

    public partial class DrawForm : Form
    {
        public DrawForm ()
        {
            InitializeComponent ();
            pictureBox.Image = new Bitmap (800, 600);
        }
 
        private int X0, Y0;
 
        private void pictureBox_MouseDown(object sender, MouseEventArgs e)
        {
            X0 = e.X;
            Y0 = e.Y;
        }
 
        private void pictureBox_MouseUp (object sender, MouseEventArgs e)
        {
           Graphics g = Graphics.FromImage (pictureBox.Image);
           Pen pen = new Pen (Color.Red);
           g.DrawLine (pen, X0, Y0, e.X, e.Y);
           pictureBox.Invalidate ();
        }
    }

Úsečka se zobrazí, až uvolníme myš.

stav na gitlabu

Náhled právě kreslené úsečky

Pokusíme se při každém pohybu myši zobrazit náhled na právě kreslenou úsečku

Přidáme proměnnou press obsahující true, pokud je myš stále ještě stisknuta.

Kreslení přesuneme do pictureBox_MouseMove

pictureBoxu přidáme (“naklikáme”) událost mouseUp

        private int X0, Y0;
        private bool press = false;
 
        private void pictureBox_MouseDown(object sender, MouseEventArgs e)
        {
            X0 = e.X;
            Y0 = e.Y;
            press = true;
        }
 
        private void pictureBox_MouseMove (object sender, MouseEventArgs e)
        {
            if (press)
            {
                Graphics g = Graphics.FromImage (pictureBox.Image);
                Pen pen = new Pen (Color.Red);
                g.DrawLine (pen, X0, Y0, e.X, e.Y);
                pictureBox.Invalidate ();
            }
        }
 
        private void pictureBox_MouseUp (object sender, MouseEventArgs e)
        {
            press = false;
        }

Program náhledy úseček kreslí, ale nemaže.

Můžete si také zkusit co se stane, když vynecháme if (press) nebo press = false

gitlab

Vytvoříme bitmapu správné velikosti

V kostruktoru vytvoříme bitmapu stejné velikosti jako je náš pictureBox.
A bitmapu vyplníme bílými body. Dosud obsahovala průhledné body.

        public DrawForm ()
        {
            InitializeComponent ();
            int w = pictureBox.Width;
            int h = pictureBox.Height;
            Bitmap b = new Bitmap (w, h);
            Graphics g = Graphics.FromImage (b);
            Brush br = new SolidBrush (Color.White);
            g.FillRectangle (br, 0, 0, w, h);
            pictureBox.Image = b;
        }

Pro vyplnění plochy si připravíme bílý štětec a
nakreslíme obdélník od (0,0) do (w-1,h-1), ale parametry zadáme (0, 0, w, h)

            g.FillRectangle (br, 0, 0, w, h);
            pictureBox.Image = b;

Na konci konstruktoru právě vytvořenou bitmapu uložíme do pictureBox.image
Funkce Invalidate zde není potřeba, protože se změnil celý “image”

Uložíme obraz před stiskem myši

Vždy při stisku myši uložíme původní obraz a před kreslením úsečky původní obraz obnovíme

V proměnné save bude odkaz (ukazatel) na objekt typu Image s původním obrázkem.

        private Image save;

Při stisku myši vytvoříme nový objekt typu Bitmap a v jeho konstruktoru do něj zkopírujeme současný obrázek.
(Třída Bitmap je odvozena z třídy Image.)

V jazyce C# jsou proměnné objektových typů odkazy, ale hvězdičky a šipky (→) jako v C++ se nepoužívají.

       save = new Bitmap (pictureBox.Image);

Před nakreslením úsečky zkopírujeme (“obtiskneme”) schovaný obrázek na souřadnici 0,0.

       g.DrawImage (save, 0, 0);

Pokud by v uschovaném obraze byly průhledné body, tak by se odpovídající body na obrazovce nezněnily.

    public partial class DrawForm : Form
    {
        public DrawForm ()
        {
            InitializeComponent ();
            int w = pictureBox.Width;
            int h = pictureBox.Height;
            Bitmap b = new Bitmap (w, h);
            Graphics g = Graphics.FromImage (b);
            Brush br = new SolidBrush (Color.White);
            g.FillRectangle (br, 0, 0, w, h);
            pictureBox.Image = b;
        }
 
        private int X0, Y0;
        private bool press = false;
        private Image save;
 
        private void pictureBox_MouseDown (object sender, MouseEventArgs e)
        {
            X0 = e.X;
            Y0 = e.Y;
            press = true;
            save = new Bitmap (pictureBox.Image);
        }
 
        private void pictureBox_MouseMove (object sender, MouseEventArgs e)
        {
            if (press)
            {
                Graphics g = Graphics.FromImage (pictureBox.Image);
                g.DrawImage (save, 0, 0);
                Pen pen = new Pen (Color.Red);
                g.DrawLine (pen, X0, Y0, e.X, e.Y);
                pictureBox.Invalidate ();
            }
        }
 
        private void pictureBox_MouseUp (object sender, MouseEventArgs e)
        {
            press = false;
        }
    }

stav z tohoto okamžiku na gitlab

 
pw/draw.txt · Last modified: 2020/10/15 21:16 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