首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将C#窗体控件转换为图像?

将C#窗体控件转换为图像?
EN

Stack Overflow用户
提问于 2009-12-10 22:25:30
回答 6查看 12.4K关注 0票数 4

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

我使用的代码类似于Panel.DrawToImage。这里有没有什么帮助,可以将整个面板保存为图片,而不仅仅是可见的部分?

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2009-12-11 02:15:01

这里没有令人满意的答案,DrawToBitmap只能绘制用户可见的内容。像预先改变面板的位置和大小这样的技巧,由于父母对控件大小的限制,通常很快就会用完。表单本身永远不会比屏幕大,现在您还将依赖于目标计算机上的视频适配器的分辨率。

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

一旦你开始考虑这样的代码,你真的应该考虑PrintDocument或报告生成器。这样做的一个好处是,打印输出看起来非常干净。由于视频和打印机分辨率的巨大差异,打印的屏幕截图总是丑陋的。

票数 2
EN

Stack Overflow用户

发布于 2009-12-10 23:17:17

我认为WM_PRINT消息会有所帮助。这是一个几乎可以工作的示例。(它仍然会打印滚动条本身,并且“超出滚动”部分的背景会丢失。)也许你可以试着让它工作,或者有更多WinForms经验的人可以把它带到下一个层次?

在您的类中声明以下内容:

代码语言:javascript
运行
复制
[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
}

然后,将控件绘制为位图:

代码语言:javascript
运行
复制
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上绘制一个虚拟背景,然后删除滚动条:

代码语言:javascript
运行
复制
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");
}
票数 4
EN

Stack Overflow用户

发布于 2009-12-10 22:39:59

考虑临时增加面板的大小,先调用p.Layout(),然后调用p.DrawToImage()

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1881317

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档