I have a form set as the IsMdiContainer
attribute to true
.
I'm trying to make it in the container "snows".
I am trying to adapt a code that works well on a normal WinForms
, but not good on MDI
container. This is what I managed to do:
public partial class SnowTest : Form
{
int num;
int[] x;
int[] y;
int[] v;
int[] s;
Random random = new Random();
System.Drawing.Graphics graphics;
Rectangle rectangle;
private MdiClient MDIContainer;
private Graphics asd;
public SnowTest()
{
InitializeComponent();
}
private void SnowTest_Load(object sender, EventArgs e)
{
SelectMdiContainer();
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.UpdateStyles();
snow();
Timer1.Start();
}
private void SelectMdiContainer()
{
foreach (Control control in this.Controls)
{
// #2
MdiClient client = control as MdiClient;
if (!(client == null))
{
MDIContainer = client;
break;
}
}
}
private void snow()
{
num = 2000;
x = new int[num];
y = new int[num];
v = new int[num];
s = new int[num];
int i = 0;
for (i = 0; i <= num - 1; i++)
{
Insnow(i);
}
}
private void Insnow(int i)
{
x[i] = random.Next(0, this.Width - 1);
y[i] = random.Next(0, this.Height * 5 / 7);
v[i] = random.Next(5, 20);
s[i] = (random.Next(1, 3) * 100 + random.Next(50, 200)) / 100;
}
private void Timer1_Tick(object sender, EventArgs e)
{
for (int i = 0; i <= num - 1; i++)
{
y[i] = y[i] + v[i];
if (y[i] >= this.Height)
{
Insnow(i);
}
}
Invalidate();
SnowOnContainer();
}
private void SnowOnContainer()
{
graphics = MDIContainer.CreateGraphics();;
int i = 0;
for (i = 0; i <= num - 1; i++)
{
graphics.FillEllipse(Brushes.White, x[i], y[i], s[i], s[i]);
}
}
private void SnowTest_Resize(object sender, EventArgs e)
{
rectangle = new Rectangle(0, 0, this.Width, this.Height);
}
}
The Timer1
is set with a Interval
of 100
The script runs and generates the "snow" but it does not remove it after a while and also the whole form creates lag.
What is the best way to achieve my goal?
In the normal form is pretty much structured in the same way, it lacks the function that select the container (SelectMdiContainer()
), the function SnowOnContainer()
and the global variable MDIContainer
.
In the form, however, there is the paint
event and consequently below carry as structured
private void SnowTest_Paint(object sender, PaintEventArgs e)
{
graphics = e.Graphics;
int i = 0;
for (i = 0; i <= num - 1; i++)
{
graphics.FillEllipse(Brushes.White, x[i], y[i], s[i], s[i]);
}
}
EDIT
I'm doing some tests. Currently I removed the function SnowOnContainer()
and added the Paint
event for the container.
private void SelectMdiContainer()
{
foreach (Control control in this.Controls)
{
// #2
MdiClient client = control as MdiClient;
if (!(client == null))
{
MDIContainer = client;
MDIContainer.Paint += OnMdiContainerPaint; //Added this Event
break;
}
}
}
The event is structured as that of the normal form but applied to the container
private void OnMdiContainerPaint(object sender, PaintEventArgs e)
{
graphics = MDIContainer.CreateGraphics();
int i = 0;
for (i = 0; i <= num - 1; i++)
{
graphics.FillEllipse(Brushes.White, x[i], y[i], s[i], s[i]);
}
}
Finally I did some research and I've added this code to avoid Flickering animation. as shown in this topic How to fix the flickering in User controls
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x02000000; // Turn on WS_EX_COMPOSITED
return cp;
}
}
In doing so it appears to be working properly with a fluid animation, but as soon as I resize the form, or I reduce to an icon returns lag