Возможно, это не тот ответ, который вы искали, но я думаю, что это альтернативная альтернатива тому, что у вас есть.
Вместо того, чтобы привлечь все слои вверх от каждого изменения, укладываю в несколько слоев друг на друга вложенности ряда PictureBoxes
в один нижний PictureBox pBox0
:
List<PictureBox> Layers = new List<PictureBox>();
private void Form1_Load(object sender, EventArgs e)
{
Layers.Add(pBox0);
setUpLayers(pBox0 , 20); // stacking 20 layers onto the botton one
timer1.Start(); // simulate changes
}
штабелирование является настроить так:
void setUpLayers(Control parent, int count)
{
for (int i = 0; i < count; i++)
{
PictureBox pb = new PictureBox();
pb.BorderStyle = BorderStyle.None;
pb.Size = parent.ClientSize;
Bitmap bmp = new Bitmap(pb.Size.Width,pb.Size.Height,PixelFormat.Format32bppPArgb);
pb.Image = bmp;
pb.Parent = i == 0 ? pBox0 : Layers[i - 1];
Layers.Add(pb);
}
}
Для лучшей производительности я использую Format32bppPArgb
как формат пикселя.
Для тестирования я бегу Tick
событие, которое случайным образом черпает на слой:
Random R = new Random(9);
private void timer1_Tick(object sender, EventArgs e)
{
int l = R.Next(Layers.Count-1) + 1;
Bitmap bmp = (Bitmap) Layers[l].Image;
using (Graphics G = Graphics.FromImage(Layers[l].Image))
{
G.Clear(Color.Transparent);
using (Font font = new Font("Consolas", 33f))
G.DrawString(l + " " + DateTime.Now.Second , font, Brushes.Gold,
R.Next(bmp.Size.Width), R.Next(bmp.Size.Height));
}
Layers[l].Image = bmp;
}
Чтобы собрать все слои в один растр вы бы использовать DrawToBitmap
метода:
Bitmap GetComposite(Control ctl)
{
Bitmap bmp = new Bitmap(ctl.ClientSize.Width, ctl.ClientSize.Height,
PixelFormat.Format32bppArgb);
ctl.DrawToBitmap(bmp, ctl.ClientRectangle);
return bmp;
}
Результат могут быть сохранены или использованы любым другим способом.
Обратите внимание, что создание слишком большого количества слоев таким образом превзойдет границы оконных ручек; Я ударил этот предел около 90 слоев. Если вам нужно больше, чем несколько десятков слоев, требуется более сложная стратегия кэширования.
Если они не меняются так часто, я бы рассмотрел возможность рисования нижних уровней в растровое изображение, которое я показываю как PictureBox.Image или даже BackgroundImage. Помимо того, что я не делаю, существует способ рисовать все растровые изображения, которые составляют общее изображение, когда кто-либо меняется. Однако вы можете кэшировать не только отдельные слои, но и их композиты; но вам все равно нужно будет воссоздать все растровые изображения с измененного слоя вверх. - Btwe: Я не уверен в вашем выборе слова: похоже, вы не столько спрашиваете об очистке __Bitmap__, но и от частей или всей вашей составной графики? – TaW
всякий раз, когда происходит изменение (скажем, движение), я повторно рисую фигуры в слое, где изменение (после очистки его цветом фона) на изображении его кеша слоя, затем рисуйте изображения всех слоев вниз вверх на картинке .image, при очистке изображения слоя с любым цветом, отличным от «прозрачного», это нормально, но если слой прозрачен (потому что это слой перекрытия), перемещенная фигура по-прежнему выполняется в обеих позициях (старая и новая). –
Давайте сделаем это ясно: вы рисуете все эти слои на вершине одного pb? не изображение? нет вложенных панелей? (которые являются хорошим способом избежать большей перерисовки ..) – TaW