[C#] Rysowanie kształtu z podglądem

Witajcie. Mam problem z małym Paintem w C#. Chcę rysować myszką prostokąt i wszystko działa, ale chciałbym żeby użytkownik przesuwając myszką widział zmianę kształtu. Jak przy rysowanieu prostokąta w prawdziwym Paincie.

Napisałem sobie kod, który to robi, ale od odrysowuje całe tło na biało (metoda Graphics.Clear()). Jak zrobić taki ficzer, żeby odrysowywało się początkowe tło, albo coś, żeby nie usuwało mi tego co już jest narysowane?

Ten kod rysuje prostokąt z odświeżeniem, ale czyści to co było rysowane wczesniej…

Point topRight = new Point(bottomRight.X, topleft.Y);

Point bottomLeft = new Point(topleft.X, bottomRight.Y);

Graphics g = pb.CreateGraphics(); //pb = picturebox

g.Clear(Color.White);

g.DrawPolygon(new Pen(new SolidBrush(Color.Pink), 3), new Point[] { topleft, topRight, bottomRight, bottomLeft });

g.Dispose();

Takiej funkcjonalności niestety w czystym GDI+ nie uświadczysz. Musisz to zaimplementować ręcznie.

Rozwiązaniem może być trzymanie kilku warstw(tutaj mogły by dwie wystarczyć - tło i zmieniający się prostokąt) i blitowanie ich przy zmianie jednej z nich(ale to też trzeba umiejętnie zrobić, bo może być ździebko niewydajne). Można też odświeżać tylko fragment PicruteBox’a, który się zmienia(czyli trzymać poprzedni prostokąt i czyścić tylko różnicę starego prostokąta i nowego, i rysować tylko różnicę nowego i starego; w sensie F1 - stary prostokąt, F2 - nowy prostokąt, czyścić: F1 \ F2; rysować: F2 \ F1).

I to jest problem… potrzebowałbym dwie “warstwy”. Tylko ta druga, do odświeżania musiałaby znów być czyszczona do białego - co nie rozwiązuje mojego problemu, albo musiałoby być przeliczane to co się pojawia na jednej i odrysowywanie różnic. Chyba nie chce mi się tego robić :confused:

Hm, będą do tego jakieś kontrolki tudzież zewnętrzne dll-ki?

Jeśli tylko jedna warstwa się zmienia, to nie czyść ją na biało, tylko na “kolor przeźroczysty” albo “czyść” blitując pierwszą warstwę.

Od tego są całe biblioteki. Patrz chociażby XNA, ANX, MonoGame itp. Dodatkowo “za darmo” otrzymujesz akcelerację sprzętową(ale to już nie jest GDI+).

“Blitując”? Czyszczenie na kolor przezroczysty skutkuje wypełnieniem do czarnego… Niby patrzę na OpenGl, coś skrobię, ale nadal nie wiem jak rozegrać tę kwestię :confused:

“Kopiując grafikę”.

A rysujesz pod spodem (oś Z ) główny obrazek? (Takie rozwiązanie jest dobre gdy masz akcelerację sprzętową, np. OpenGl; Bez akceleracji lepiej blitować).

PictureBox nie obsługuje przeźroczystości, ale czyste GDI+ już tak. Wystarczy, że cały czas operujesz na System.Drawing.Image i na samym końcu uaktualniasz PictureBox.

Sample:

var bmpA = new Bitmap(600, 600); // Tło

var bmpB = new Bitmap(600, 600); // Kwadrat

using (var gB = Graphics.FromImage(bmpB))

{

	gB.Clear(Color.Transparent);				

	gB.FillRectangle(Brushes.Red, 100, 100, 200, 200);

}

using (var gA = Graphics.FromImage(bmpA)) //Można(należy) użyć trzecią, wynikową powierzchnię, i to ją przypisywać do PB, ale tutaj tego nie potrzeba, więc pominąłem.

{

	gA.Clear(Color.Blue);

	gA.DrawImage(bmpB, 0, 0);

}


this.pictureBox1.Image = bmpA;