使用.NET将可滚动面板另存为PDF

时间:2011-04-20 15:36:08

标签: c# pdf-generation screenshot

我有一个面板,里面装满了很多控件供用户填写。这些包括文本框,复选框,单选按钮等。这是一个填充的长形式,因此控件位于可滚动面板中。我需要的是将整个面板保存为pdf。我认为PDFsharp是一个很好的库,可以将任何文本或图像保存为pdf文件,但我不想为面板内的每个控件编写代码。我曾经写过一个类来从Control对象创建一个pdf文件。它正在迭代给定控件的所有内部控件(及其内部控件,直到没有内部控件),并使用其位置和大小属性将其Text属性(可擦除控件的是/否)写入pdf。我现在找不到它,但我记得我使用的一些DevExpress控件存在问题所以我没有再费心去写它了。 (编辑:我必须,你可以在下面找到它。)我认为截取屏幕并将该图像保存为pdf会很好但我无法找到如何实现它。 This question似乎是这样,但没有令人满意的答案。

所以,截图与否我对任何建议都持开放态度。在很多情况下,用户必须填写长格式并能够将其保留为pdf格式。再次,任何建议或解决方法将不胜感激。 (我考虑使用html创建表单,在WebBrowser控件中显示它并使用html到pdf库但我真的更喜欢使用我现有的表单)

非常感谢。


修改 我必须写一些东西迭代容器控件的内部控件(如面板)并使用它们的位置,大小和字体属性将每个内部控件写入pdf,但我不建议使用它(至少原样)因为这些:

  1. 它将页面大小设置为给定控件的大小,并仅使用一个(通常是巨大的)pdf页面。如果需要,可以添加逻辑以将其拆分为页面。 (我没有,但我想你可能需要你的pdf更适合打印机)。
  2. Cheeso的方法(使用FlowDocument)对于像这样的任务来说是一种更“合法”的方式。我更喜欢使用它,但在这种情况下我没有选择。
  3. 我在这段代码中使用了PDFsharp。您可以在it's hompageit's CodePlex page中找到它。

    PdfReport类:

        private PdfDocument Document;
        public Control Control { get; private set; }        
    
        public PdfReport(Control control) { Control = control; }
    
        public PdfDocument CreatePdf(PdfDocument document = null)
        {
            Document = document != null ? document : new PdfDocument();
            PdfPage page = Document.AddPage();
            page.Height = Control.Height;
            page.Width = Control.Width;
    
            XGraphics gfx = XGraphics.FromPdfPage(page);
            foreach (PdfItem item in CreatePdf(new Point(0, 0), Control.Controls))
            {
                XStringFormat format = item.IsContainer ? XStringFormats.TopLeft : item.TextAlign == ContentAlignment.BottomCenter ? XStringFormats.BottomCenter : item.TextAlign == ContentAlignment.TopLeft ? XStringFormats.TopLeft : item.TextAlign == ContentAlignment.TopCenter ? XStringFormats.TopCenter : XStringFormats.Center;
                gfx.DrawString(item.Text, item.Font, item.Brush, new XRect(item.Location, item.Size), format);
            }
            return Document;
        }
        private IEnumerable<PdfItem> CreatePdf(Point location, Control.ControlCollection controls)
        {
            List<PdfItem> items = new List<PdfItem>();
            foreach (Control control in controls)
            {
                if (control.Controls.Count > 0)
                    items.AddRange(CreatePdf(control.Location, control.Controls));
                items.Add(new PdfItem(control, location));
            }
            return items;
        }
    
        public void SaveAsPdf(string path, bool open = false)
        {
            CreatePdf().Save(path);
            if (open)
                Process.Start(path);
        }
    

    PdfItem类:

        public string Text { get; set; }
        public Point Location { get; set; }
        public Size Size { get; set; }
        public Font Font { get; set; }
        public bool IsContainer { get; set; }
        public ContentAlignment TextAlign { get; set; }
        public Color ForeColor { get; set; }
        public XBrush Brush { get { return new SolidBrush(ForeColor); } }
    
        public PdfItem() { }
        public PdfItem(string text, Point location, Font font, Color foreColor, Size size, bool isContainer = false, ContentAlignment alignment = ContentAlignment.MiddleCenter)
        {
            Text = text;
            Location = location;
            Size = size;
            Font = new Font(font.FontFamily, font.Size, font.Style, GraphicsUnit.World);
            TextAlign = alignment;
            ForeColor = foreColor;
            IsContainer = isContainer;
        }
        public PdfItem(string text, Point location, Size size)
            : this(text, location, new Font("Calibri", 12), Color.Black, size) { }
        public PdfItem(Control control, Point parentLocation)
            : this(control.Text, control.Location, control.Font, control.ForeColor, control.Size, control.Controls.Count > 0)
        {
            Location = new Point(Location.X + parentLocation.X, Location.Y + parentLocation.Y);
            IEnumerable<PropertyInfo> properties = control.GetType().GetProperties();
            if (properties.FirstOrDefault(p => p.Name == "TextAlign" && p.PropertyType == typeof(ContentAlignment)) != null)
                TextAlign = (control as dynamic).TextAlign;
            if (properties.FirstOrDefault(p => p.Name == "Checked" && p.PropertyType == typeof(bool)) != null)
            {
                string title = control.Text != null && control.Text.Length > 0 ? string.Format("{0}: ", control.Text) : string.Empty;
                Text = string.Format("{0}{1}", title, (control as dynamic).Checked ? "Yes" : "No");
            }
        }
    

3 个答案:

答案 0 :(得分:2)

关于

  

。我认为截取屏幕并将该图像保存为pdf会很好但我无法找到如何实现它。

codeplex.com上有一个名为“cropper”的工具。它旨在用作可以截取屏幕截图的用户工具。它是托管代码,开源。

我可以想象将一些裁剪器魔法嵌入到您的应用中,以便您可以拍摄该截图。我还可以想象这对于在出现问题时收集屏幕的诊断图像很有用。

另一方面......如果你有兴趣制作一个在屏幕上再现内容的印刷版,那么我认为你应该使用WPF,在这种情况下做你想要的很容易。例如,this question描述了如何为FlowDocument执行打印预览。从那时起,您的用户可以打印到PDF(如果他安装了PDF打印机)或打印到XPS,或打印到物理输出设备,等等。

答案 1 :(得分:1)

我不知道这是否对您有所帮助,但DocRaptor.com的pdf api可以内置,因此无论用户输入什么,它都可以为您完成。它使用基本的HTML。

答案 2 :(得分:0)

正如您可以使用以下内容:)

#include <string>
using namespace std;
string MyString = "My C++ String"
if( MyString.compare("My C++ String")==0 ) { 
    // If there is 0 difference between the two strings...
    cout << "This will now be run!" << endl;
}

Clipboard.SetImage会将你发送到剪贴板,这样你就可以将它们粘贴到你的pdf表格或任何文件中

这里面还有一个示例,可以根据需要将其保存为图像。

这里的诀窍是为您的面板自动调整大小。它需要设置为true,以便面板将整个区域调整为可见,然后在您完成工作后立即将其调整为false,以便再次为用户屏幕使用滚动条(您可能会看到它闪烁半秒,但这段代码确实有用。

将其保存为PDF我个人更喜欢将其作为剪贴板写入,或者您可以写入字节。但是ITextSharp是一个很棒的扩展库供你使用!

我真的希望这会有所帮助。