C#Windows窗体控件到图像?

我正在尝试创建Panel的图像并将其保存到文件夹中。 问题是面板有滚动条,生成的图像仅适用于Panel的可见部分。

我使用的代码类似于Panel.DrawToImage。 可以在这里有任何帮助将整个Panel保存为图片而不仅仅是可见部分吗?

这里没有满意的答案,DrawToBitmap只能绘制用户可见的内容。 由于父母施加的控制尺寸的限制,预先改变面板的位置和尺寸的技巧通常会快速耗尽气体。 表单本身永远不会比屏幕大,现在您还将依赖于目标计算机上video适配器的分辨率。

一个丑陋的黑客是多次运行DrawToBitmap,在每次调用之间更改Panel的AutoScrollPosition属性。 您必须将生成的图像拼接在一起。 当然要特别注意最后一个因为它不会像其他那么大。

一旦你开始考虑这样的代码,你真的应该考虑PrintDocument或报告生成器。 这样做的一个好处是打印输出看起来更像是清洁剂。 由于video和打印机分辨率的巨大差异,打印的屏幕截图总是很​​难看。

我认为WM_PRINT消息会有所帮助。 这是一个几乎可以工作的样本。 (它仍会打印滚动条本身,并且背景在“滚动”部分中丢失。)也许您可以使用它并使其正常工作,或者具有更多WinForms经验的人可以将其提升到新的水平?

在您的class级中声明以下内容:

[DllImport("user32.dll")] public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam); private const int WM_PRINT = 791; ///  /// The WM_PRINT drawing options ///  [Flags] private enum DrawingOptions { ///  /// Draws the window only if it is visible. ///  PRF_CHECKVISIBLE = 1, ///  /// Draws the nonclient area of the window. ///  PRF_NONCLIENT = 2, ///  /// Draws the client area of the window. ///  PRF_CLIENT = 4, ///  /// Erases the background before drawing the window. ///  PRF_ERASEBKGND = 8, ///  /// Draws all visible children windows. ///  PRF_CHILDREN = 16, ///  /// Draws all owned windows. ///  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"); } 

编辑:这是一个替代的涂料策略,可能会让你得到你想要的。 我正在做一些假设,但也许它会起作用。 它首先在Bitmap上绘制虚拟背景,并删除滚动条:

 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()函数?

嗯……这听起来像(正如你在原始问题中没有这样说的那样)但是你会在面板的容器里面装一个图片盒作为容器,即嵌套容器吗?

你有没有考虑这样做:

 //假设pic是PictureBox的类型,并且已分配image属性
 PictureBox图片;

 //并且图片框嵌入了Panel变量ppControls.Add(pic);

 // ...

 //那么为什么不这样做呢?
 pic.Image.Save(...); 

Image类的Save方法有5个重载,因此在您方便时选择一个。

希望这会有所帮助,最好的问候,汤姆。

我创建一个具有正确大小的位图(并用正确的颜色清除它或将面板的背景图像绘制到它上),然后遍历所有子控件和.DrawToImage将它们中的每一个都放到正确的位置。

你需要让你的面板AutoZize=TrueAutoScroll=False ,而不是把它放到另一个容器中并使容器AutoScroll=true