0
votes

I am implementing a winform application and I need a rectangle moving around with the pointer. I am creating it on timer_tick as below. The only problem is that it is flickering. How can I eliminate the flickering?

 private void timer1_Tick(object sender, EventArgs e)
    {
      //Gets the Mouse position on the X-axis
        int posX = MousePosition.X;
        //Gets the mouse poisiton on the Y-Axis
        int posY = MousePosition.Y;

        Graphics g = Graphics.FromHwnd(IntPtr.Zero);

        mouseNewRect = new Rectangle(new Point(posX, posY), new
               Size(500, 500));
        g.DrawRectangle(new Pen(Brushes.Chocolate), mouseNewRect);
        this.Refresh();
    }
1
First, look into double-buffering. Second, you should only update some field in the Tick event and call Invalidate. Keep painting to the Paint handler. Third, if you do the second option properly, really you don't need a timer you can just use the MouseMove event to track the mouse and call Invalidate. - Anthony
Enable double buffering. If the problem persists, ditch the timer and render the box from the paint method. - User 12345678
Why you drawing the rectangle in desktop? I mean why using Graphics.FromHwnd(IntPtr.Zero) ? Btw you ought to dispose the Graphics object once you're done. - Sriram Sakthivel
Maybe it is just because the timer's interval is not set properly. Set it somewhere between 20ms and 100ms (10Fps~50Fps). - kennyzx
No, the flicker is only the least of your problems! Go for Anthony's advice and make sure you follow all of it !!! - TaW

1 Answers

1
votes

Just to add more detail to my comment above, here's a sample control which demonstrates how to setup double-buffering as well as how to hook into the paint event handling properly.

class CustomControl : Control
{
    private bool mShouldDrawMouseRect;
    private Rectangle mMouseRect;

    public CustomControl()
    {
        this.mMouseRect.Width = 500;
        this.mMouseRect.Height = 500;

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

    protected override void OnMouseEnter(EventArgs e)
    {
        // No actual painting done here, just updating fields.
        this.mShouldDrawMouseRect = true;
        this.Invalidate();
    }

    protected override void OnMouseLeave(EventArgs e)
    {
        // No actual painting done here, just updating fields.
        this.mShouldDrawMouseRect = false;
        this.Invalidate();
    }

    protected override void OnMouseMove(MouseEventArgs e)
    {
        // No actual painting done here, just updating fields.
        this.mMouseRect.X = e.X;
        this.mMouseRect.Y = e.Y;
        this.Invalidate();
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        // ALL painting stays in the paint event, using the graphics provided
        if (this.mShouldDrawMouseRect)
        {
            // If you're just using named colors, we can access the static Pen objects.
            e.Graphics.DrawRectangle(Pens.Chocolate, this.mMouseRect);

            // If you create your own Pen, put it in a Using statement.
            // Including the following commented example:

            // using (var pen = new Pen(Color.Chocolate))
            // {
            //     e.Graphics.DrawRectangle(pen, this.mMouseRect);
            // }
        }
    }
}