Hej. Przepraszam, że jeszcze raz męczę i dodatkowo zakładam nowy wątek, ale ten problem jest jednak inny niż poprzedni toteż nie chcę go mieszać.
Przedstawię krótko sytuację:
- Moim celem było stworzenie szybkiego i wydajnego kursora do prostej aplikacji graficznej. Kursor ów miał osiągnąć niezłą wydajność najlepiej bez malowania na obrazku.
Doszedłem w końcu - przy Waszej pomocy - do pomysłu, aby stworzyć przezroczysty PicureBox i na nim malować kursor. Zalety tego rozwiązania są takie: - Nie ważny jest rozmiar faktycznego obrazka - kursor i tak nie będzie na nim malowany
- Szybkość działania praktycznie natychmiastowa.
i faktycznie tak jest, ale... (I tu następuje problem) nie wiem jak odświeżać w ten sposób obrazek.
Przedstawiam tutaj kod mojego przezroczystego PictureBox-a:
class TransPictureBox : Control
{
private Image _image = null;
private Bitmap _bmp = null;
public Image Image
{
get
{
return _image;
}
set
{
_image = value;
}
}
public Bitmap BMP
{
get
{
return _bmp;
}
set
{
_bmp = value;
}
}
public TransPictureBox()
{
}
public void AutoSizeMy()
{
}
protected override void OnPaintBackground(PaintEventArgs pevent)
{
}
protected override void OnPaint(PaintEventArgs pe)
{
if (Image != null)
pe.Graphics.DrawImage(Image, 0, 0);
}
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x20;
return cp;
}
}
protected override void OnMove(EventArgs e)
{
RecreateHandle();
}
}
Tutaj go tworzę:
private TransPictureBox pan;
public Form1()
{
InitializeComponent();
pan = new TransPictureBox();
pan.Parent = this;
pan.Width = this.Width;
pan.Height = this.Height;
pan.Left = 0;
pan.Top = 0;
pan.BringToFront();
this.DoubleBuffered = true;
this.pan.MouseMove += MouseMoveTransparentPicture;
}
Jak widać PictureBox ten ma leżeć sobie bezpośrednio na całej formatce (całym faktycznym obrazku).
Ponieważ PictureBox ten jest przezroczysty to będzie widać wszystko pod nim.
Pod zdarzeniem MouseMove następuje rysowanie kursora i wygląda to tak:
private void MouseMoveTransparentPicture(object sender, MouseEventArgs e)
{
Graphics g = this.pan.CreateGraphics();
g.DrawEllipse(new Pen(new SolidBrush(Color.Black), 3),
e.X - 25, e.Y - 25, 50, 50);
g.Dispose();
}
Oczywiście tutaj nie następuje żadne refreshowanie, czyli kursor jest malowany cały czas jeden po drugim. Wygląda to jak malowanie pędzlem o dziwnym kształcie.
Moje pytanie brzmi: Jak odświeżać przezroczysty PictureBox. Jak odświeżyć jego Graphics?
Próbowałem oczywiście standardowych rzeczy jak:
this.pan.Refresh();
albo próbowałem kopiować w ten sposób:
Graphics g = this.pan.CreateGraphics();
Bitmap b = new Bitmap(this.pan.Width, this.pan.Height);
Graphics g2 = Graphics.FromImage(b);
g2.DrawEllipse(new Pen(new SolidBrush(Color.Black), 3),
e.X - 25, e.Y - 25, 50, 50);
g.DrawImage(b, 0, 0);
g2.Dispose();
g.Dispose();
b.Dispose();
Niestety to wszystko nie daje żadnych rezultatów.
Także próbowałem po prostu:
this.pan.Image = b;
Ale z racji tego, że PictureBox jest przezroczysty to nic nie widać i również takie przypisanie nie daje żadnych wyników.
Stosowałem również funkcję Clear:
g2.Clear(Color.Transparent);
albo
g2.Clear(Color.White);
I to dawało rezultat odświeżania, ale z kolei cały obraz był biały + kursor, ale nie było widać nic pod PictureBoxem (traciłem jego przezroczystość).
W jaki sposób sobie z tym poradzić?
W jaki sposób odświeżyć przezroczysty PictureBox?
Bo powiem szczerze, że wydajność kursora teraz jest zachwycająca i jeśli uda się pokonać przeszkodę z odświeżaniem to ten dość uciążliwy problem z całym kursorem zniknie :)