Я разрабатываю настольное приложение с использованием С#, Winforms и MS Visual Studio 2010. В приложении я должен снять скриншот панели формы и сохранить изображение на диске. Размер панели может быть большой. Я использовал метод Panel.DrawToBitmap(), чтобы сохранить изображение панели. Но, когда размер панели слишком велик, он генерирует исключение. Я нашел в msdn (http://msdn.microsoft.com/en-us/library/system.windows.forms.control.drawtobitmap%28v=vs.110%29.aspx), что для управления большими размерами метод Control.DrawToBitmap не будет работать. Есть ли альтернативный способ, я могу добиться аналогичного поведения, преодолевающего ограничение по размеру. Следует отметить, что размер панели может меняться.
Обновление: я нашел альтернативу Control.DrawToBitmap: WebBrowser.DrawToBitmap() или другие методы? , Но он захватывает только видимую часть элемента управления.
Этот вопрос меня смутил из-за нескольких вещей.
Вот решение, которое записывает файл изображения из Panel
довольно больших размеров.
Одним из ограничивающих факторов является размер результирующего растрового изображения. Я тестировал размеры до 12.5k * 25k
И нашел, что он работает нормально; однако размеры могут зависеть от вашей машины. Я думаю, вам нужна довольно некоторая непрерывная память для создания такого большого Bitmap
.
Другая проблема заключается в том, что, как указывает ваш заголовок, действительно с DrawToBitmap
метода DrawToBitmap
. Похоже, что он не может надежно записывать на большие растровые изображения, поэтому мне пришлось буферизировать его результаты во временном растровом изображении. Он также не может работать, если какой-либо размер элемента управления превышает некоторый размер, возможно, 4k, но, возможно, нет.
Сначала решение создает Bitmap
размера Panel
. Затем он создает временную Panel
для размещения большой Panel
. Этот контейнер достаточно мал, чтобы DrawToBitmap
работал.
Затем он перебирает ширину и высоту, перемещая большую Panel
вверх и влево, вставляя части DrawToBitmap
возвращается шаг за шагом в большой Bitmap
.
Наконец, он записывает его как PNG
для лучшей читаемости и размера.
private void button2_Click(object sender, EventArgs e)
{
Bitmap bmp = new Bitmap(largePanel.ClientSize.Width, largePanel.ClientSize.Height);
DrawToBitmap(largePanel, bmp); // the patchwork method
bmp.Save(yourFileName, System.Drawing.Imaging.ImageFormat.Png);
bmp.Dispose(); // get rid of the big one!
GC.Collect(); // not sure why, but it helped
}
void DrawToBitmap(Control ctl, Bitmap bmp)
{
Cursor = Cursors.WaitCursor; // yes it takes a while
Panel p = new Panel(); // the containing panel
Point oldLocation = ctl.Location; //
p.Location = Point.Empty; //
this.Controls.Add(p); //
int maxWidth = 2000; // you may want to try other sizes
int maxHeight = 2000; //
Bitmap bmp2 = new Bitmap(maxWidth, maxHeight); // the buffer
p.Height = maxHeight; // set up the..
p.Width = maxWidth; // ..container
ctl.Location = new Point(0, 0); // starting point
ctl.Parent = p; // inside the container
p.Show(); //
p.BringToFront(); //
// we'll draw onto the large bitmap with G
using (Graphics G = Graphics.FromImage(bmp))
for (int y = 0; y < ctl.Height; y += maxHeight)
{
ctl.Top = -y; // move up
for (int x = 0; x < ctl.Width; x += maxWidth)
{
ctl.Left = -x; // move left
p.DrawToBitmap(bmp2, new Rectangle(0, 0, maxWidth, maxHeight));
G.DrawImage(bmp2, x, y); // patch together
}
}
ctl.Location = p.Location; // restore..
ctl.Parent = this; // form layout <<<==== ***
p.Dispose(); // clean up
Cursor = Cursors.Default; // done
}
Я нарисовал несколько вещей на Panel
и выбросил несколько сотен Buttons
и результат выглядит без проблем. Не могу опубликовать его по понятным причинам..
*** Примечание. Если ваша панель не сидит на форме, вы должны изменить this
на настоящего Parent
!