The typical Subclassing solution:
The subclassing solution is to create a subclass of the Control and use this lines in all the constructors, after InitializeComponents:
DoubleBuffered = true; SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint, true);
But this can be really hard when you have a lot of controls or a Form already designed. Instead of this, we will use some reflection.
I give you two options, set the DoubleBuffered property to true, or use the Styles if there isn't a DoubleBuffered property in the control. Here are the examples:
Setting DoubleBuffered to true:
I used a DataGridView which actually have a DoubleBuffered property.
typeof(DataGridView).GetProperty("DoubleBuffered",System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(dataGridView, true, null);
Using SetStyle method:
But what happen if the Control doesn't have DoubleBuffered? We can't use it so, we need a workaround. We should use the SetStyles method to do it but, surprisingly, you can't use it because is not public. So here's come the reflection method:
typeof(TableLayoutPanel).GetMethod("SetStyle", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(tableLayoutIngredients, new Object[] { ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint, true });
But I'm so lazy to copy paste all this code so...
Using Extension Methods:
In order to don't repeat code, i made a class which adds two extension methods. The class is the following:
public static class ControlExtensions { public static Boolean SetDoubleBuffered(this Control control, Boolean isDoubleBuffered) { PropertyInfo property = control.GetType().GetProperty("DoubleBuffered", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); if (property != null) { property.SetValue(control, isDoubleBuffered, null); return true; } return false; } public static Boolean SetStylesOfControl(this Control control, ControlStyles styles, Boolean value) { MethodInfo method = control.GetType().GetMethod("SetStyle", BindingFlags.Instance | BindingFlags.NonPublic); if (method != null) { method.Invoke(control, new Object[] { styles, value }); return true; } return false; } }
You can use it to set the values as follows:
// DataGridView have DoubleBuffered so this method will set it to true and return true. dataGridView.SetDoubleBuffered(true); // TableLayoutPanel doesn't have DoubleBuffered so use SetStyles. tableLayoutIngredients.SetStylesOfControl(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint, true);
But if you are working with Controls, and you want to set recursively this property, you can do it this way:
// If it returns false is beacause can't set DoubleBuffered (Maybe the control don't have it) if(!control.SetDoubleBuffered(true)) // So we set the styles aaaand it's done. control.SetStylesOfControl(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint, true);
This uses the boolean returned by try to set the DoubleBuffered to set the styles (or no). I hope this helps you.
No hay comentarios:
Publicar un comentario