Click here to Skip to main content
15,883,983 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
We all know how Invalidate works.
1. I create Vector image and draw it on Bitmap.
2. Invalidate redraws Bitmap on Form1 every time regardless me.
3. I make modifications to Bitmap when Invalidate attempts to redraw it.

So, what to do?

Note: I have to use only .Net libraries, not Platform Invoke.
Posted
Updated 12-Mar-15 8:43am
v6

The next way works, but it lags a bit, because Form1 acts like it loses its Focus.

Code:
C#
public static class SuspendUpdate
{
    private const int WM_SETREDRAW = 0x000B;

    public static void Suspend(Control control)
    {
        Message msgSuspendUpdate = Message.Create(control.Handle, WM_SETREDRAW, IntPtr.Zero,
            IntPtr.Zero);

        NativeWindow window = NativeWindow.FromHandle(control.Handle);
        window.DefWndProc(ref msgSuspendUpdate);
    }

    public static void Resume(Control control)
    {
        IntPtr wparam = new IntPtr(1);
        Message msgResumeUpdate = Message.Create(control.Handle, WM_SETREDRAW, wparam,
            IntPtr.Zero);

        NativeWindow window = NativeWindow.FromHandle(control.Handle);
        window.DefWndProc(ref msgResumeUpdate);

        control.Invalidate();
    }
}


Using:
C#
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            this.Paint += Draw;
            (new Thread(Method)).Start();
        }

        Bitmap bitmap = new Bitmap(200, 200);

        private void Draw(object sender, PaintEventArgs e)
        {
            e.Graphics.DrawImage(bitmap, 0, 0);
        }

        private void Method()
        {
            using (Graphics g = Graphics.FromImage(bitmap))
                g.Clear(Color.Red);

            this.Invoke(new Action(delegate
            {
                SuspendUpdate.Suspend(this); // Suspend
            }));

            bitmap = new Bitmap(100, 100); // Modificate while Suspended
            using (Graphics g = Graphics.FromImage(bitmap))
                g.Clear(Color.Yellow);
            this.Invalidate(); // Invalidate does't draw

            this.Invoke(new Action(delegate
            {
                SuspendUpdate.Resume(this); // Resume
                this.Invalidate();
                this.Activate(); // Active Form1 because it loses Focus
            }));
        }
    }

    public static class SuspendUpdate
    {
        private const int WM_SETREDRAW = 0x000B;

        public static void Suspend(Control control)
        {
            Message msgSuspendUpdate = Message.Create(control.Handle, WM_SETREDRAW, IntPtr.Zero,
                IntPtr.Zero);

            NativeWindow window = NativeWindow.FromHandle(control.Handle);
            window.DefWndProc(ref msgSuspendUpdate);
        }

        public static void Resume(Control control)
        {
            IntPtr wparam = new IntPtr(1);
            Message msgResumeUpdate = Message.Create(control.Handle, WM_SETREDRAW, wparam,
                IntPtr.Zero);

            NativeWindow window = NativeWindow.FromHandle(control.Handle);
            window.DefWndProc(ref msgResumeUpdate);

            control.Invalidate();
        }
    }
}
 
Share this answer
 
v4
The next way works 100% sure:
C#
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        this.Paint += Draw;
    }

    Bitmap bitmap = new Bitmap(100, 100);
    bool ok = true;

    Bitmap bitmapSaved = new Bitmap(100, 100);
    bool saved = false;

    private void Draw(object sender, PaintEventArgs e)
    {
        if (ok)
            e.Graphics.DrawImage(bitmap, 0, 0);
        else
        {
            if (!saved)
            {
                using (Graphics g = Graphics.FromImage(bitmapSaved))
                    g.DrawImage(bitmap, 0, 0);
                saved = true;
            }

            e.Graphics.DrawImage(bitmapSaved, 0, 0);
        }
    }

    private void Thread()
    {
        ok = false;
        this.Invoke(new Action(delegate
        {
            this.Refresh();
        }));
        using (Graphics g = Graphics.FromImage(bitmap))
        {
            // Modificate bitmap
        }

        ok = true;
        saved = false;
    }
}
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900