Rysowanie w WinForms (problem z algorytmem)

0

Chcę stworzyć program wprawkę, w wielkim skrócie ma to wyglądać tak, że rysuję na panelu szereg punktów, kiedy kliknę na jeden z nich i przytrzymam wcisniety klawisz myszy, chce go przesuwać po panelu (przerysowwywanie panelu podczas MouseMove), kiedy puszczę punkt klawisz myszy, punkt zostaje na ostatniej pozycji z MouseMove i pozostaje statyczny obraz.

Mam problem z obsługą tego algorytmu, poniżej to co wymyśliłem,

 
        private void ObszarRysowania_MouseDown(object sender, MouseEventArgs e)
        {
            for (int i = 0; i < punktyNarysowane.Count; i++)
            {
                double wynik = 0;
                wynik = ObliczOdlegloscMiedzyPunktami(e.X, punktyNarysowane[i].WspX, e.Y, punktyNarysowane[i].WspY);

                if (wynik <= czuloscTrafienia)
                {
                    TrafionyPunkt = punktyNarysowane[i];
                    break;
                }
            }
        }

        private double ObliczOdlegloscMiedzyPunktami(double x1, double x2, double y1, double y2)
        {
            return Math.Sqrt(Math.Pow((x1 - x2), 2) + Math.Pow((y1 - y2), 2));
        }


        private void ObszarRysowania_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)  //czy to to samo co sprawdzić czy lewy klawisz jest nadal wciśnięty??
            {
                TrafionyPunkt.WspX = e.X;
                TrafionyPunkt.WspY = e.Y;
                NarysujZadanePunkty();
            }

            TBcursorPosX.Text = e.Location.X.ToString();
            TBcursorPosY.Text = e.Location.Y.ToString();
        }

        private void ObszarRysowania_MouseUp(object sender, MouseEventArgs e)
        {
            TrafionyPunkt = null;
        }

Ale nie wiem czy to powyżej działa ponieważ, w chwili gdy kliknę na jakiś punkt program wywala mi błąd w klasie Punkt w metodzie Rysuj w linii:

 
                g.FillEllipse(sb, WspX - 3, WspY - 3, 6, 6);  // <-- Parameter is not valid (Argument Exception was UnHandled)
                g.DrawString(this.ToString(), f, sb, new Point(WspX - 20, WspY - 15)); 

Nie wiem o co chodzi bo podczas startu programu, rysuje wszystkie punkty OK, dopiero gdy na któryś kliknę, całość zatrzymuje mi się na tej włsśnie lini, prosiłbym o nakierowanie na źródło problemu.

0

A debugier to ci kosmici wycieli?

0

w debugerze wyłapuje tylko:

Załóżmy współrzędne punktu "A" (240; 120),
to przy najmniejszej zmianie w MouseMove, wywala błąd przy (241;120)

są to wspX, i wspY

nic mi to nie mówi, nie wiem o co chodzi.

0

w: private void ObszarRysowania_MouseMove(object sender, MouseEventArgs e)
if (TrafionyPunkt!=null)

0

robiłem jeszcze próby z SolidBrush'em

był w using, potem wyciągnąłem spoza metody jako pole klasy - bez zmian

potem zrobiłem próbe z zakomentowaniem w ogóle linii rysowania elipsy, także mój puntk na rysunku składał się tylko z tekstu
mimo wszsytko jak klikałem "na czuja" i próbowałem przeciągnąć na rysunku punkt w którymś momencie w niego trafiłem i identyczny błąd wyskoczył mi dla linii rysującej opis punktu, o co tu chodzi?

0

pokaż przynajmniej deklaracje wszystkiego co tu używasz.

0

dla punktu:

 

public int WspX { get; set; }
public int WspY { get; set; }

SolidBrush sb = new SolidBrush(Color.Black)
Font f = new Font("Arial", 6f);

Dla okna z obszarem rysowania:

private List<Punkt> punktyNarysowane = new List<Punkt>();
Graphics g;

        private void ObszarRysowania_Paint(object sender, PaintEventArgs e)
        {
            g = e.Graphics;
            g.SmoothingMode = SmoothingMode.AntiAlias;

            if (CHBsiatka.Checked)
            {
                RysowanieSiatki(g);
            }

            NarysujZadanePunkty();
        }
 

czyli g przypisuje tylko w metodzie Paint obszaru rysowania Formy i pozniej to g po prostu jest w formie i to g przekazuje w metodzie NarysujZadanePunkty() kolejnym punktom które "same sie rysuja".

0

Czy to:
public int WspX { get; set; }
public int WspY { get; set; }
jakiś skrót myślowy ?
Chodzi mi o to czy właśnie tak masz wpisane czy coś skasowałeś żeby za dużo nie wklejać?
Bo to nie ma racji bytu!
Jeżeli własnie tak masz to zamień to na:
public int WspX;
public int WspY;

0

Kolejny trop:

 
        private void ObszarRysowania_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left && TrafionyPunkt!=null)
            {
                
                TrafionyPunkt.WspX = e.X;
                TrafionyPunkt.WspY = e.Y;
                g.Clear(Color.White);             // ten sam bład, to obiekt Graphics rzuca ten wyjatek
                NarysujZadanePunkty();
            }

            TBcursorPosX.Text = e.Location.X.ToString();
            TBcursorPosY.Text = e.Location.Y.ToString();
        }

Debugując, spróbowałem czyścić obszar rysowania przed przerysowaniem i okazało się że to obiekt Graphics rzuca ten wyjątek, tylko nadal nie wiem dlaczego.

0

Rozwiązaniem problemu jest:

 

private void ObszarRysowania_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left && TrafionyPunkt!=null)
            {
 
                TrafionyPunkt.WspX = e.X;
                TrafionyPunkt.WspY = e.Y;
                ObszarRysowania.Invalidate();
                ObszarRysowania.Update();
            }
 
            TBcursorPosX.Text = e.Location.X.ToString();
            TBcursorPosY.Text = e.Location.Y.ToString();
        }

tylko nie wiem dlaczego, jak ktoś wie to byłbym widzęczny za wyjasnienie.

1

tylko nie wiem dlaczego, jak ktoś wie to byłbym widzęczny za wyjasnienie.

Naprawdę chcesz wiedzieć?
Bo Windows Forms to wrapper na WinAPI. A w WinAPI rysować można po oknie w odpowiedzi na komunikaty WM_PAINT i WM_PAINTBKGND. Poza tymi zdarzeniami jest rysowanie jest dozwolone tylko pomiedzy ręcznym wywołaniem BeginPaint a EndPaint.
Komunikatowi WM_PAINT WinAPI odpowiada zdarzenie WinForms OnPaint.

1 użytkowników online, w tym zalogowanych: 0, gości: 1