I think the WM_PRINT message is going to be helpful. Here's a sample that almost works. (It still prints the scrollbars themselves, and the background is lost on the "out of scroll" portions.) Perhaps you can play with this and get it working, or someone with more WinForms experience can take this to the next level?
Declare the following in your class:
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
private const int WM_PRINT = 791;
/// <summary>
/// The WM_PRINT drawing options
/// </summary>
[Flags]
private enum DrawingOptions
{
/// <summary>
/// Draws the window only if it is visible.
/// </summary>
PRF_CHECKVISIBLE = 1,
/// <summary>
/// Draws the nonclient area of the window.
/// </summary>
PRF_NONCLIENT = 2,
/// <summary>
/// Draws the client area of the window.
/// </summary>
PRF_CLIENT = 4,
/// <summary>
/// Erases the background before drawing the window.
/// </summary>
PRF_ERASEBKGND = 8,
/// <summary>
/// Draws all visible children windows.
/// </summary>
PRF_CHILDREN = 16,
/// <summary>
/// Draws all owned windows.
/// </summary>
PRF_OWNED = 32
}
Then, to paint the control to a bitmap:
using (Bitmap screenshot = new Bitmap(this.panel1.DisplayRectangle.Width, this.panel1.DisplayRectangle.Height))
using (Graphics g = Graphics.FromImage(screenshot))
{
try
{
SendMessage(this.panel1.Handle, WM_PRINT, g.GetHdc().ToInt32(), (int)(DrawingOptions.PRF_CHILDREN | DrawingOptions.PRF_CLIENT | DrawingOptions.PRF_NONCLIENT | DrawingOptions.PRF_OWNED));
}
finally
{
g.ReleaseHdc();
}
screenshot.Save("temp.bmp");
}
EDIT: Here's an alternate paint strategy that might get you what you're looking for. I'm making some assumptions, but perhaps it will work. It paints a dummy background on the Bitmap first, and also removes the scrollbars:
using (Bitmap screenshot = new Bitmap(this.panel1.DisplayRectangle.Width, this.panel1.DisplayRectangle.Height))
using (Graphics g = Graphics.FromImage(screenshot))
{
g.FillRectangle(SystemBrushes.Control, 0, 0, screenshot.Width, screenshot.Height);
try
{
SendMessage(this.panel1.Handle, WM_PRINT, g.GetHdc().ToInt32(), (int)(DrawingOptions.PRF_CHILDREN | DrawingOptions.PRF_CLIENT | DrawingOptions.PRF_OWNED));
}
finally
{
g.ReleaseHdc();
}
screenshot.Save("temp.bmp");
}