Avatar billede zuran Nybegynder
01. marts 2009 - 13:32 Der er 12 kommentarer og
1 løsning

MouseMove event for langsom til at tegne

Hej.

Jeg har forsøgt at lave en lille Windows applikation, hvor man skal kunne tegne, ved at holde venstre museknap nede.

Det fungere sådan, så når MouseMove event køres (Når musen bevæges), så hvis venstre museknap holdes ned, så sættes der en enkel pixel på musens placering.

Men MouseMove event er alt for langsom, til at kunne registrere musens bevægelser. Dvs. at når man vil tegne, så bliver det ikke flydende linier, men istedet en masse prikker.

Meningen var sådan set, at man skulle kunne tegne, ligesom i Paint f.eks. Er der nogle, der har en løsning på mit problem?

Tak på forhånd.
Avatar billede aaberg Nybegynder
01. marts 2009 - 14:17 #1
I stedet for at tegne en prik hver gang MouseMove eventet kører, skal du tegne en streg fra sidste punkt.
Avatar billede aaberg Nybegynder
01. marts 2009 - 14:31 #2
Her er et simpelt eksempel

using System.Drawing;
using System.Windows.Forms;

namespace EkspertenTest
{
    public partial class TegneForm : Form
    {
        private Bitmap theImage;

        private Point currentPoint;
        private Point lastPoint;

        private bool mouseIsDown = false;

        public TegneForm()
        {
            InitializeComponent();

            this.theImage = new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height);
            this.DoubleBuffered = true;
        }

        private void TegneForm_MouseDown(object sender, MouseEventArgs e)
        {
            currentPoint = lastPoint = this.PointToClient(Control.MousePosition);
            mouseIsDown = true;

            this.PaintLine();
        }

        private void TegneForm_MouseMove(object sender, MouseEventArgs e)
        {
            if (mouseIsDown)
            {
                lastPoint = currentPoint;
                currentPoint = this.PointToClient(Control.MousePosition);
                this.PaintLine();
            }
        }

        private void TegneForm_MouseUp(object sender, MouseEventArgs e)
        {
            this.mouseIsDown = false;
        }

        private void PaintLine()
        {
            using (Graphics g = Graphics.FromImage(this.theImage))
            {
                using (Pen thePen = new Pen(Color.Blue, 2f))
                {
                    g.DrawLine(thePen, lastPoint, currentPoint);
                }
            }

            this.Invalidate();
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            e.Graphics.DrawImage(this.theImage, new Point(0, 0));
        }

       
    }
}
Avatar billede zuran Nybegynder
01. marts 2009 - 15:28 #3
Jeg kan simpelthen ikke få det til at fungerer i min nuværende applikation, selv efter at have prøvet i et godt stykke tid.

Men jeg prøvede så lige at oprette en ny test applikation, og så blot copy/paste fra dit eksempel, hvorved det virkede.

Dvs. det bare er mig der lige skal have det sat ordenligt i min nuværende applikation.

Tak for hjælpen, vil du smide et svar?
Avatar billede aaberg Nybegynder
01. marts 2009 - 15:33 #4
:-)
Avatar billede zuran Nybegynder
01. marts 2009 - 21:40 #5
Jeg ved ikke om du stadig følger med i spørgsmålet, men jeg fandt lige ud af, hvad "problemet" er, mht. min nuværende applikation.

Der tegnes ikke på selve formen, men derimod på en pictureBox. Efter at have rettet en hel del "this." til "pictureBox1." ( F.eks pictureBox1.Invalidate(); ) virker det stadig ikke.

Der bliver simpelthen ikke tegnet nået. Jeg håber derfor du lige stadig har fat om spørgsmålet, og kan hjælpe mig.
Avatar billede aaberg Nybegynder
02. marts 2009 - 09:13 #6
Kan du ikke copy/paste koden ind her, så skal jeg se om jeg kan spotte fejlen?
Avatar billede zuran Nybegynder
02. marts 2009 - 15:36 #7
Jo selvfølgelig.

Kommer her:

        public Form1()
        {
            InitializeComponent();
        }

        Point lastPoint;
        Point currentPoint;

        Bitmap paintBitmap;

        private void Form1_Load(object sender, EventArgs e)
        {
            paintBitmap = new Bitmap(pictureBox1.ClientRectangle.Width, pictureBox1.ClientRectangle.Height);
            this.DoubleBuffered = true;
        }

        private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                lastPoint = currentPoint;
                currentPoint = pictureBox1.PointToClient(Control.MousePosition);
                paint();
            }
            else if (e.Button == MouseButtons.Right)
            {
                lastPoint = currentPoint;
                currentPoint = pictureBox1.PointToClient(Control.MousePosition);
                paint();
            }
        }

        private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                currentPoint = lastPoint = pictureBox1.PointToClient(Control.MousePosition);

                paint();
            }
        }

        private void paint()
        {
            using (Graphics g = Graphics.FromImage(paintBitmap))
            {
                using (Pen paintPen = new Pen(Color.Black, 1))
                {
                    g.DrawLine(paintPen, lastPoint, currentPoint);
                }
            }

            pictureBox1.Invalidate();
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            e.Graphics.DrawImage(paintBitmap, new Point(0, 0));
        }


----------------------------------------------------------

Der bliver ikke skrevet nogen fejlmeddelser, når jeg tester applikationen med F5. Men jeg har testet mig lidt frem, og ved at den nederste "protected override void onPaint(PaintEventArgs e)" ikke bliver kørt, hvilket må være grunden til, at der ingenting bliver skrevet.
Avatar billede aaberg Nybegynder
02. marts 2009 - 15:44 #8
Prøv at tilføje følgende linje i Form1_Load metoden:

this.pictureBox1.Image = this.paintBitmap;
Avatar billede zuran Nybegynder
02. marts 2009 - 16:08 #9
Hej, og tak for det hurtige svar.

Det gjorde desværre ingen forskel...
Avatar billede zuran Nybegynder
02. marts 2009 - 18:20 #10
Så fik jeg det sgu til at virke, efter at have rodet med det i noget tid.

Linien du sagde, jeg skulle prøve at tilføje, skulle alligevel vær der:

this.pictureBox1.Image = this.paintBitmap;

Og så skulle jeg også lige have denne:

paintBitmap = new Bitmap(pictureBox1.ClientRectangle.Width, pictureBox1.ClientRectangle.Height);

Grunden til at jeg skal have nederste med, er pga. af man har mulighed for at oprette "nye" sider man kan tegne på, og som standard har pictureBoxen 0 width og 0 height, hvilket du jo ikke kunne vide.

Jeg har så blot placeret begge linier ind, under når pictureBoxen's size ændres.

Tak for hjælpen!
Avatar billede aaberg Nybegynder
02. marts 2009 - 18:22 #11
Godt at du fandt ud af det :-)
Avatar billede windcape Praktikant
05. marts 2009 - 11:58 #12
Intet af overstående er dog optimalt. Du bør benytte dig af GraphicsPath til formålet.
Avatar billede windcape Praktikant
05. marts 2009 - 11:59 #13
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace DrawingPad.Tools
{
    class BrushTool : IDrawingTool
    {
        private Pen drawingPen;
        private GraphicsPath mousePath;
        private DrawingPanel panel;
        private bool isPainting = false;

        public Color Color
        {
            get { return drawingPen.Color;  }
            set { drawingPen.Color = value; }
        }
       
        public BrushTool(DrawingPanel panel)
        {
            this.panel = panel;
            this.panel.Cursor = Cursors.Cross;   
           
            drawingPen = new Pen(Color.FromArgb(250, Color.Black), 4);
            mousePath  = new GraphicsPath();
           
            drawingPen.LineJoin = LineJoin.Round;
            drawingPen.StartCap = LineCap.Round;
            drawingPen.EndCap  = LineCap.Round;           
        }
   
        public void Paint(PaintEventArgs e)
        {       
            e.Graphics.SmoothingMode    = SmoothingMode.AntiAlias;
            e.Graphics.PixelOffsetMode  = PixelOffsetMode.HighQuality;
            e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
           
            foreach(ColoredGraphicsPath path in panel.Paths)
            {
                e.Graphics.DrawPath(
                    path.DrawingPen, path.GraphicsPath
                );
            }
           
            e.Graphics.DrawPath(drawingPen, mousePath); 
        }

        public void MouseDown(MouseEventArgs e)
        {
            if(e.Button == MouseButtons.Left)
            {
                isPainting = true;
                mousePath.StartFigure();
            }
        }
       
        public void MouseMove(MouseEventArgs e)
        {
            if(isPainting)
            {
                mousePath.AddLine(e.X, e.Y, e.X, e.Y);
                panel.Invalidate();
            }
        }
       
        public void MouseUp(MouseEventArgs e)
        {
            if(isPainting)
            {
                isPainting = false;
                panel.Paths.Add(
                    new ColoredGraphicsPath(drawingPen, mousePath)
                );
                mousePath.Reset();
            }
        }
       
        public void MouseClick(MouseEventArgs e)
        {
            if(e.Button == MouseButtons.Left)
            {
                mousePath.AddLine(e.X, e.Y, e.X + 1, e.Y + 1);           
                panel.Invalidate();
            }
        }   
    }
}

namespace DrawingPad
{
    class DrawingPanel : System.Windows.Forms.Panel
    {
        private List<ColoredGraphicsPath> paths;
       
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public List<ColoredGraphicsPath> Paths
        {
            get { return paths;  }
            set { paths = value; }
        }
       
        public DrawingPanel()
        {
            this.DoubleBuffered = true;
            this.paths = new List<ColoredGraphicsPath>();
        }
    }
   
    class ColoredGraphicsPath
    {
        public GraphicsPath GraphicsPath { get; set; }
        public Pen DrawingPen { get; set; }
       
        public ColoredGraphicsPath(Pen pen, GraphicsPath path)
        {
            this.DrawingPen  = (Pen)pen.Clone();
            this.GraphicsPath = (GraphicsPath)path.Clone();
        }
    }
}
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester