我正在尝试创建一个面板的图像并将其保存到文件夹中。问题在于该面板具有滚动条,生成的图像仅针对面板的可见部分。
我使用的代码类似于Panel.DrawToImage。是否有任何帮助可以保存整个面板作为图片而不仅仅是可见部分?
我认为WM_PRINT消息会很有帮助。这里有一个几乎可以工作的示例(它仍然打印滚动条本身,并且背景在“超出滚动”部分丢失)。也许您可以尝试调整一下并使其正常工作,或者有更多WinForms经验的人可以将其提升到下一个级别?
在您的类中声明以下内容:
[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
}
然后,将控件绘制到位图上:
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");
}
编辑:这里有一种替代的绘制策略,可能可以帮助你达到目标。我做了一些假设,但也许它会起作用。首先在位图上绘制虚拟背景,并且去除滚动条:
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");
}
考虑暂时增加面板的大小,调用 p.Layout(),然后 p.DrawToImage()
DrawToImage()
函数?嗯...听起来(因为你在原始问题中没有这么说),你是否有一个作为容器的picturebox,位于面板容器内,也就是嵌套容器?
您考虑过这样做吗:
// 假设 pic 是 PictureBox 类型,并且已经分配了图像属性 PictureBox pic;
// 并且该 picturebox 嵌入在面板变量 p 中。 p.Controls.Add(pic);
// ...
// 那么为什么不这样做呢? pic.Image.Save(...);
Image 类的 Save
方法有 5 种重载形式,可以根据自己的需求选择。
希望对您有所帮助, 此致, Tom。
你需要将你的面板设置为 AutoZize=True
和 AutoScroll=False
,然后将其放入另一个容器中,并将该容器设置为 AutoScroll=true
。