2009-12-10 81 views
4

我想创建一个面板的图像并将其保存到一个文件夹。问题在于面板上有滚动条,生成的图像仅用于面板的可见部分。C#Windows窗体控制图像?

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

回答

2

这里没有快乐的答案,DrawToBitmap只能绘制对用户可见的内容。诸如改变面板的位置和尺寸之类的技巧通常由于父母对控制尺寸的限制而迅速耗尽。窗体本身永远不会比屏幕大,现在您还将依赖目标机器上视频适配器的分辨率。

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

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

+0

谢谢!这似乎是目前唯一的方法!虽然有点工作!再次感谢!! – Shri 2009-12-10 22:21:44

+0

嘿家伙只是在这个更新.... 一个解决方法是在内存中创建相同的控制,以及定义自定义高度和宽度,然后调用DrawToBitmap函数! 是一个甜蜜的成功!希望这可以帮助别人! – Shri 2009-12-11 06:39:42

+1

用于PrintDocument – hometoast 2009-12-11 14:44:06

0

嗯...听起来像(你在原始问题中没有这么说),但是你有一个图框作为面板容器内的容器,即嵌套容器吗?

你有没有考虑这样做:

 
// Assume pic is the type of PictureBox and the image property is assigned 
PictureBox pic; 

// And that the picturebox is embedded in the Panel variable p. 
p.Controls.Add(pic); 

// ... 

// So why not do this? 
pic.Image.Save(...); 

Image类的Save方法有5个重载所以选择一个在您方便的。

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

+2

我想他想在屏幕上“截取”一个容器控件。 – hometoast 2009-12-10 14:36:49

+0

@hometoast:哦...现在我明白了......呃...... Alt + PrtScrn怎么样,并将其粘贴到mspaint中?或者其他一些屏幕抓取工具?总之,答案是否定的,因为无论图像是否被裁剪,屏幕捕捉的内容都不存在! – t0mm13b 2009-12-10 14:45:58

1

考虑暂时提高面板的尺寸,要求p.Layout(),然后p.DrawToImage()

+0

控制大于屏幕的显示大小。所以滚动条是不可能摆脱! – Shri 2009-12-10 22:20:01

1

也许你可以在需要的尺寸克隆控制到另一个(隐藏)的形式(这样滚动条没有显示),并打电话给你的DrawToImage()函数?

4

我认为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"); 
} 
0

我想创建一个具有正确大小的位图(与正确的颜色清除或漆面板的背景图片吧),然后遍历所有子控件和.DrawToImage它们中的每一个到正确的位置。

0

你需要使你的面板AutoZize=TrueAutoScroll=False,比放到另一个容器,并使容器AutoScroll=true