简体   繁体   中英

How do I prevent pictureBox images from trailing while I move it?

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 PictureBox es 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 Image s onto the panel.

Here is an example 在此处输入图片说明

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 PictureBox es background Image to a random large detailed image. The trailing effect occurs when I move pictureBox1 and I can reproduce this every time.

您是否尝试过从OnPaint处理程序调用基础的OnPaint或从MouseMove进行选择性的Invalidate / Refresh?

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;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM