我正在尝试创建Panel的图像并将其保存到文件夹中。问题是面板有滚动条,而生成的图像仅用于面板的可见部分。
我使用的代码类似于Panel.DrawToImage。这里有没有什么帮助,可以将整个面板保存为图片,而不仅仅是可见的部分?
发布于 2009-12-11 02:15:01
这里没有令人满意的答案,DrawToBitmap只能绘制用户可见的内容。像预先改变面板的位置和大小这样的技巧,由于父母对控件大小的限制,通常很快就会用完。表单本身永远不会比屏幕大,现在您还将依赖于目标计算机上的视频适配器的分辨率。
一个丑陋的技巧是多次运行DrawToBitmap,在每次调用之间更改面板的AutoScrollPosition属性。您必须将生成的图像缝合在一起。当然要特别注意最后一个,因为它不会像其他的那么大。
一旦你开始考虑这样的代码,你真的应该考虑PrintDocument或报告生成器。这样做的一个好处是,打印输出看起来非常干净。由于视频和打印机分辨率的巨大差异,打印的屏幕截图总是丑陋的。
发布于 2009-12-10 23:17:17
我认为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");
}
编辑:这里有一个替代的绘画策略,可能会让你得到你想要的东西。我做了一些假设,但也许它会起作用。它首先在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");
}
发布于 2009-12-10 22:39:59
考虑临时增加面板的大小,先调用p.Layout(),然后调用p.DrawToImage()
https://stackoverflow.com/questions/1881317
复制相似问题