Как преодолеть ограничение большого размера метода Control.DrawToBitmap () в winform

1

Я разрабатываю настольное приложение с использованием С#, 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() или другие методы? , Но он захватывает только видимую часть элемента управления.

  • 0
    О каких числах мы говорим? Можете ли вы дать нам размеры, которые вам могут понадобиться?
  • 0
    Это происходит последовательно или сначала после того, как ваша программа некоторое время работала? В последнем случае, возможно, вам нужно избавиться от некоторых ресурсов - см. Здесь: stackoverflow.com/questions/11996335/…
Показать ещё 10 комментариев
Теги:
winforms

1 ответ

1

Этот вопрос меня смутил из-за нескольких вещей.

Вот решение, которое записывает файл изображения из 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 !

  • 0
    Вы решили свои проблемы?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню