1

Hello stackoverflow community. I already tried looking for a similar question but I only found questions about flickering, which isn't the same as the problem I am having.

I need help preventing the PictureBoxes from trailing whenever I move them across a panel. The application I am making is similar to MS Paint. When I click a PictureBox I can click and drag it using:

private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{            
    x = e.X;
    y = e.Y;
}

private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left)
    {
        pictureBox1.Left += (e.X - x);
        pictureBox1.Top += (e.Y - y);
    }
}

and the other pictureBoxes which I did Not click are painted to the DoubleBuffered panel, using:

private void panel1_Paint(object sender, PaintEventArgs e)
{
    foreach (PictureBox pb in pboxes)
    {
        if (!pb.Visible)
        {
            e.Graphics.DrawImage(pb.BackgroundImage, new Rectangle(pb.Location, pb.Size));
        }
    }
}

For some reason when I drag a PictureBox it's background Image drags across the painted panel.

Weird thing is, this only happens on the Paint event. If I were to make the panel's background Image something, the moving PictureBox won't trail. It only happens when I'm painting Images onto the panel.

Here is an example enter image description here

I would greatly appreciate any help, thanks.

I simplified the code so it'll be easier to understand.(The trailing effect still occurs)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections;

namespace WindowsFormsApplication1

{

public partial class Form1 : Form
{

    int x;
    int y;

    public Form1()
    {
        InitializeComponent();
        pictureBox1.Show();
        pictureBox2.Hide();
        pictureBox3.Hide();
    }

    private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
    {            
        x = e.X;
        y = e.Y;
        panel1.Invalidate();
    }

    private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            pictureBox1.Left += (e.X - x);
            pictureBox1.Top += (e.Y - y);
        }
    }

    private void panel1_Paint(object sender, PaintEventArgs e)
    {
        e.Graphics.DrawImage(pictureBox2.BackgroundImage, new Rectangle(pictureBox2.Location, pictureBox2.Size));
        e.Graphics.DrawImage(pictureBox3.BackgroundImage, new Rectangle(pictureBox3.Location, pictureBox3.Size));
    }


}}

And it uses this doubleBuffered panel class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public class DoubleBufferPanel : Panel
    {


        public DoubleBufferPanel()
        {

            // Set the value of the double-buffering style bits to true.
            this.DoubleBuffered = true;



            this.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.UserPaint |
             ControlStyles.AllPaintingInWmPaint, true);

            this.UpdateStyles();

        }


    }

}

Now my code calls for 3 PictureBox, and 1 DoubleBuffered panel.

The form is maximized, Panel1.size = (2000, 1200); and each PictureBox size = (700, 700) and set each PictureBoxes background Image to a random large detailed image. The trailing effect occurs when I move pictureBox1 and I can reproduce this every time.

brain56
  • 2,659
  • 9
  • 38
  • 70
kev
  • 101
  • 1
  • 10
  • Did you try calling `Refresh()` or `Invalidate()` on the panel? – wasyl Aug 25 '12 at 22:48
  • Yes I have wasyl. Both in the pictureBox1 mouse down event, and I tried the Paint event which did not work. – kev Aug 25 '12 at 22:49
  • 1
    You could try double buffering. Take a look at this codeproject article: http://www.codeproject.com/Articles/12870/Don-t-Flicker-Double-Buffer – Luc Morin Aug 25 '12 at 22:53
  • sorry if I didn't make it clear mrlucorin, but I already had created a doublebuffered panel. Still doesn't prevent the trailing, altho it prevents the flickering. – kev Aug 25 '12 at 22:55
  • Have you tried with images with very small file size which requires less process? or this is the same for any kind of image? – Dumbo Aug 27 '12 at 08:53
  • Sean87 no sadly file size doesn't matter. Whenever I move a large pictureBox across a doublebuffered panel, its moving pictureBox always has it's background Image trail across the panel. I have no idea how to fix it. – kev Aug 27 '12 at 16:04

2 Answers2

0

Have you tried calling the base's OnPaint from your OnPaint handler or alternately doing a selective Invalidate/Refresh from the MouseMove?

  • thanks for the response codingthewheel. Are you referring to the OnPaint event inside the doublebufferedpanel class? Because it's a custom class named DoubleBufferedPanel.cs. – kev Aug 26 '12 at 17:52
0

I know that this was years ago, but I was having similar trouble today. I was click-and-dragging a PictureBox for magnifying an image section. The issues were solved by getting the right order of operations: size, move, paint. I solved the issue by:

  1. Instantiating the PictureBox during the form's Load event

  2. Relocating the PictureBox with its Location property during the MouseMove event

  3. Invalidating the PictureBox after the relocation

  4. Redrawing during the Paint event, which was triggered via Invalidate()

  5. I had a custom shape (Region) for my PictureBox, which was set during the VisibleChange event.*

  6. The PictureBox was only visible (Visible == true) if the left mouse button was pressed, and the image was large enough.*

    * = optional

Here are modified excerpts from my code. I hope that they are sufficiently relevant.

public Form1()
{
    InitializeComponent();

    this.Paint += new System.Windows.Forms.PaintEventHandler(Form1_Paint);
    Main_PictureBox.Paint += new PaintEventHandler(Main_PictureBox_Paint);
    Main_PictureBox.MouseDown += new MouseEventHandler(StartZoom);
    Zoom_PictureBox.MouseDown += new MouseEventHandler(StartZoom);
    Main_PictureBox.MouseMove += new MouseEventHandler(MoveZoom);
    Main_PictureBox.MouseUp += new MouseEventHandler(EndZoom);
    Main_PictureBox.MouseLeave += new EventHandler(EndZoom);
    Zoom_PictureBox.MouseUp += new MouseEventHandler(EndZoom);
    Zoom_PictureBox.VisibleChanged += new EventHandler(Zoom_PictureBox_VisibleRegion);
    Zoom_PictureBox.Paint += new PaintEventHandler(Zoom_PictureBox_Paint);
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
    int H = flowLayoutPanel1.Height - flowLayoutPanel1.Margin.Size.Height;
    Main_PictureBox.MinimumSize = new Size(0, 0);
    Main_PictureBox.MaximumSize = new Size(flowLayoutPanel1.Width, H);
}
private void Main_PictureBox_Paint(object sender, PaintEventArgs e)
{
    Main_PictureBox.Parent.MaximumSize = Main_PictureBox.Size + Main_PictureBox.Margin.Size;
}
private void DisplayImage(object sender, EventArgs e)
{
    Image img = ((PictureBox)sender).Image;

    int W = img.Width;
    int H = img.Height;
    float ratio = (float)W / (float)H;

    Main_PictureBox.Image = img;
    Main_PictureBox.Size = new Size(W, H);
    float TestRatio = ((float)Main_PictureBox.Width / (float)Main_PictureBox.Height);
    if (TestRatio < ratio)
        Main_PictureBox.Height = (int)((float)Main_PictureBox.Width / ratio);
    else if (TestRatio > ratio)
        Main_PictureBox.Width = (int)((float)Main_PictureBox.Height * ratio);
}
private void Zoom_PictureBox_VisibleRegion(object sender, EventArgs e)
{
    using (var gp = new System.Drawing.Drawing2D.GraphicsPath())
    {
        gp.AddEllipse(new Rectangle(0, 0, this.Zoom_PictureBox.Width, this.Zoom_PictureBox.Height));
        this.Zoom_PictureBox.Region = new Region(gp);
    }
}
private void Zoom_PictureBox_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.DrawImage(Main_PictureBox.Image, e.ClipRectangle, cropRectangle, GraphicsUnit.Pixel);
}
private void StartZoom(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left && scale > 1.25)
    {
        int dX = Zoom_PictureBox.Width / 2;
        int dY = Zoom_PictureBox.Height / 2;
        Zoom_PictureBox.Visible = true;
        Zoom_PictureBox.Location = new Point(e.X - dX, e.Y - dY);
    }
}
private void MoveZoom(object sender, MouseEventArgs e)
{
    if (Main_PictureBox.Image != null)
    {
        Zoom_PictureBox.Visible = (e.Button == MouseButtons.Left && scale > 1.25);
        if (Zoom_PictureBox.Visible && e.Button == MouseButtons.Left)
        {
            int dX = Zoom_PictureBox.Width / 2;
            int dY = Zoom_PictureBox.Height / 2;

            Zoom_PictureBox.Location = new Point(e.X - dX, e.Y - dY);
            Zoom_PictureBox.Invalidate();
        }
    }
}
private void EndZoom(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left)
        EndZoom();
}
private void EndZoom(object sender, EventArgs e)
{
    EndZoom();
}
private void EndZoom()
{
    Zoom_PictureBox.Visible = false;
}
private Rectangle cropRectangle
{
    get
    {
        if (Main_PictureBox.Image != null)
        {
            Point origin = Main_PictureBox.PointToScreen(new Point(0, 0));
            float X = (float)(MousePosition.X - origin.X);
            return new Rectangle(
                (int)(scale * X) - Zoom_PictureBox.Width / 2,
                (int)(scale * (float)(MousePosition.Y - origin.Y)) - Zoom_PictureBox.Height / 2,
                Zoom_PictureBox.Width,
                Zoom_PictureBox.Height);
        }
        else
            return new Rectangle();
    }
}
private float scale
{
    get
    {
        if (Main_PictureBox.Image != null)
            return (float)Main_PictureBox.Image.Height / (float)Main_PictureBox.Height;
        else
            return 0;
    }
}
Community
  • 1
  • 1
GarrettML
  • 1
  • 5