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=True
和AutoScroll=False
,而不是把它放到另一个容器中并使容器AutoScroll=true
。