How to overcome the winform's Control.DrawToBitmap() method large size limitation

前端 未结 1 483
挽巷
挽巷 2020-12-21 19:40

I am developing an desktop application using C#, Winforms, and MS Visual Studio 2010. In the application, I have to take the screenshot of a panel of a form and save the ima

相关标签:
1条回答
  • 2020-12-21 20:45

    This question had me confused about quite a few things..

    Here is a solution that writes an image file from a Panel of rather large sizes..

    One of the limiting factors is the size of the resulting Bitmap. I have tested for sizes of up to 12.5k * 25k and found it to work fine; the sizes may depend on your machine, though. I think you need quite some contiguous memory to create such a large Bitmap.

    The other problem is, as your title suggests, indeed with the DrawToBitmap method itself. It looks as if it can't reliably write onto large Bitmaps, which is why I had to buffer its results in a temporary Bitmap. Nor can it work if any dimension of the control is over some size, maybe 4k, but maybe not..

    The solution first creates a Bitmap of the Panel's size. Then it creates a temporary Panel to house the large Panel. This container it small enough for DrawToBitmap to work.

    Then it loops over the width and height, moving the large Panel up and left, pasting the portions DrawToBitmap brings back, step by step into the large Bitmap.

    Finally it writes it back as PNG for best readability and size..

    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
    }
    

    I have drawn a few things onto the Panel and thrown in a few hundred Buttons and the result looks seamless. Can't post it, for obvious reasons..

    *** Note: If your Panel doesn't sit on the form you should change this to the real Parent!

    0 讨论(0)
提交回复
热议问题