0

I'm having trouble with a Bitmap flicking when it's moved or resized. I'm basically making a paint type application which will also include layers similar to that of photoshop.

I've set the scroll wheel to zoom/resize the Bitmap and set the middle mouse button to move the panel while it is held down and moving.

I have a panel with a checkered background image which is set to tile. This is so that the background pattern stays the same size when resizing. This panel is basically used to set the size of a Bitmap and have a background.

Here is a video of of the issue: https://youtu.be/HRcCGaPmNU0

Here is the script that draws and moves with the irrelevant stuff removed.

 public Canvas()
    {
        InitializeComponent();
        this.SetStyle(ControlStyles.ResizeRedraw, true);
        this.MouseWheel += new MouseEventHandler(Canvas_WheelZoom);
        this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.DoubleBuffer | ControlStyles.SupportsTransparentBackColor, true);
        this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);

    }
 private void panel_DrawArea_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
    {
        Graphics g;
        g = e.Graphics;
        //--------LAYERS--------//
        layerCount = layerBMPs.Count;
        if (layerCount > 0)
        {
            for (int i = 0; i < layerCount; i++)
            {
                Console.WriteLine("Draw Layer");
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
                g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half;
                g.DrawImage(layerBMPs[i], 0, 0, canvasSize.Width, canvasSize.Height);
            }
        }
        //--------LAYERS--------//

        //--------GRID--------//
        Console.WriteLine("Draw Grid");
        Bitmap gridArea;
        gridArea = new Bitmap(canvasSize.Width, canvasSize.Height);
        Pen myPen = new Pen(Brushes.Black);
        int tileCountX = canvasSize.Width / tileSize.Width;
        int tileCountY = canvasSize.Height / tileSize.Height;
        for (int i = 0; i < tileCountX; i++)
        {
            g.DrawLine(myPen, i * tileSize.Width * canvasScale, 0, i * tileSize.Width * canvasScale, canvasSize.Height);
        }
        for (int j = 0; j < tileCountY; j++)
        {
            g.DrawLine(myPen, 0, j * tileSize.Height * canvasScale, canvasSize.Width, j * tileSize.Height * canvasScale);
        }
        //--------GRID--------//
        g.Dispose();
        myPen.Dispose();
        }
    //Clicking the canvas
    private void panel_DrawArea_MouseDown(object sender, MouseEventArgs e)
    {
        //Detect which mouse button is pressed
        switch(MouseButtons)
        {
            case MouseButtons.Middle:
                //Move Canvas
                canvasMove = 1;
                canvasMoveX = e.X;
                canvasMoveY = e.Y;
                break;
        }
    }
    private void panel_DrawArea_MouseMove(object sender, MouseEventArgs e)
    {
        //Detect which mouse button is pressed
        switch (MouseButtons)
        {
            case MouseButtons.Middle:
                //Move Canvas
                if (canvasMove == 1)
                {
                    int xPos = Cursor.Position.X - canvasMoveX - this.Location.X;
                    int yPos = Cursor.Position.Y - canvasMoveY - this.Location.Y - 16;

                    drawAreaPos = new Point(xPos, yPos);

                    panel_DrawArea.Refresh(); <--- This makes it flicker really fast when moving or resizing.
                    //panel_DrawArea.Invalidate(); <--- Does nothing
                }

                break;
        }
    }
    private void panel_DrawArea_MouseUp(object sender, MouseEventArgs e)
    {
        switch (MouseButtons)
        {
            case MouseButtons.Middle:
                //Move Canvas
                canvasMove = 0;
                break;
        }
    }

So basically what happens here is that the list contains bitmaps. The loop in the draw event draws those bitsmaps. Once all of them have been drawn then the grip is drawn on top.

I've tried double buffering and endless ammounts of playing about with no success.

Is anyone able to help?

Thanks

SmellyFox
  • 29
  • 5
  • Make the Panel [DoubleBuffered](https://stackoverflow.com/questions/44185298/update-datagridview-very-frequently/44188565#44188565) - _I've tried double buffering_ - How did you try that? Also : Invalidate ought to work!! – TaW Sep 19 '18 at 19:43
  • @TaW Hi Thanks for replying. I've had ago at setting it to double buffer as the top of the script. I've been having trouble setting the panel to be double buffered.. As I understand its protected. When I try and make a subclass of the panel and try and use it I always get an error stating it doesn't exist in my project or something. I'll try and recreate it. – SmellyFox Sep 19 '18 at 19:54
  • @TaW Hi, so I've make a subclass of Panel which is pretty much the same as the one here: http://gregback.net/double-buffered-panels-in-c.html When I open an Image it crashes and returns: System.ArgumentException error. – SmellyFox Sep 19 '18 at 20:07
  • Instead of a subclass the function in my link will also make any control doublebuffered. – TaW Sep 19 '18 at 20:19
  • @TaW Ok I've found that using the following lines in the panel class is causing the error: this.SetStyle(ControlStyles.DoubleBuffer, true); or this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); Which is not good as theyre the params I want to change – SmellyFox Sep 19 '18 at 20:22
  • Why even have them there?? If you have a subclass you can directly set DoubleBuffered=true; in the constructor. – TaW Sep 19 '18 at 20:24
  • @TaW Ok I've managed it. The System.ArgumentException error was caused by the g.dispose on the draw event. now using the custom subclass with OptimizedDoubleBuffer true seams to do the job! – SmellyFox Sep 19 '18 at 20:55

0 Answers0