如何打印文本框中的内容

14

我该如何在Metro应用程序中打印文本框(TextBox)的内容?我已经阅读了MSDN上的快速入门指南和许多在线教程,但它们非常复杂并且无法使用TextBox控件,只能使用RichTextBox控件

我们如何从Metro应用程序中的TextBox控件打印内容?是否可能?怎么做?


@TwoMore 抱歉,不是重复问题 - 那个问题没有回答。它根本不起作用。 - jay_t55
@CodyGray 确实,打印似乎很复杂。我在网上看到的所有代码都涉及RichTextBox控件,并且整个代码都基于您使用RichTextBox这一事实。当我简单地更改其中的一些部分,使其没有对RichTextBox进行引用 - 只有TextBox时,它不起作用(正如我所预期的那样) - 这让我产生了一个问题 - 我们如何使用TextBox打印?似乎还没有人做过这个。 - jay_t55
3
为什么会有人点踩?这不是重复的问题。这里的其他问题和答案都没有回答我的问题,而且提供的代码是针对RichTextBox控件的,而且不起作用。 - jay_t55
1
在Windows Forms中,做任何非平凡的事情都需要远远超过“几行代码”的工作量。不过我承认,Windows 8的构思和设计都很糟糕。(另外请注意,我不是那些给你点踩的人。这是一个完全合理的问题。我只是想让你提供更多细节。) - Cody Gray
@CodyGray 这并不复杂。伙计们,看看我下面的答案。它很直接了当。你只需要理解逻辑流程。打印可以在任何UIElement上运行...只要你确保正确地设置样式。 - Alexandru
显示剩余3条评论
3个回答

7

更新1

我创建了一个帮助类,简化了打印文本框内容的过程。你可以通过NuGet添加这个帮助类。如果你想增强我的现有帮助类,请在GitHub上进行分支。


这里我提供了来自MSDN的修改后的打印示例。我加入了一个文本框,你可以在里面写任何东西并将其打印出来。请注意,我没有编写完全与文本框文本相同的样式(粗体、斜体、下划线、颜色)的示例。我设置了硬编码的打印格式。你可以制作自己的格式。

Stack Overflow中的答案有字符限制,我的代码太长了,所以发布到了CodePaste.net上。

XAML : http://codepaste.net/9nf261

CS : http://codepaste.net/q3hsm3

请注意,我使用了一些图片,所以请将图片放在“Images”文件夹中。


4
在回答中添加一个代码下载链接并不是一个好的解决方案。如果你从Skydrive上删除了该文件,则此答案将变得无用。把代码作为答案的一部分包含进来。 - John Koerner
2
我从不删除我的公共样例。然后我也在这里发布代码。 - Farhan Ghumra
@Xyroid 谢谢你做这个。我在这一行遇到了 NullReferenceException: PrintingRoot.Children.Add(page); 但我不知道为什么会有 null 值? - jay_t55
我没有遇到任何问题,我建议你创建一个新项目,并从我的Skydrive中使用我的代码。我的Skydrive项目已经由我测试过了。 - Farhan Ghumra
2
我认为代码太长无法适应SO是一个很好的指示,表明在Metro应用程序中从TextBox打印纯文本过于复杂和不必要。 - jay_t55
显示剩余2条评论

6

我刚刚创建了一个小型的WinForms应用程序,其中包含一个文本框(textBox1)和一个按钮(button1)。代码如下:

public partial class Form1 : Form
{
    public Form1()
    {
           InitializeComponent();
    }

    private void PrintDocumentOnPrintPage(object sender, PrintPageEventArgs e)
    {
        e.Graphics.DrawString(this.textBox1.Text, this.textBox1.Font, Brushes.Black, 10, 25);
    }

    private void button1_Click(object sender, EventArgs e)
    {
        PrintDocument printDocument = new PrintDocument();
        printDocument.PrintPage += PrintDocumentOnPrintPage;
        printDocument.Print();
    }
}

点击按钮后将进行打印。

2
这个问题涉及到Windows商店应用程序,这是一个完全不同的东西。 - John Koerner
2
这个问题涉及到Windows Store应用程序,这与Windows Forms应用程序非常不同。 - Farhan Ghumra
2
WinForms中只需要4行代码,而Metro应用程序可能需要数百行——这是为什么????只是为了打印一个TextBox的内容,其中可能只有一个字符吗?微软真的搞砸了这个。 - jay_t55

0
我敦促您在这里检查我的问题,其中我阐述了一个最简单的情况,您可以从页面上打印出某些内容(您可以将该代码添加到任何当前页面上 - 只需将我用于示例文本框的文本替换为您想要的任何内容)。他们使用富文本框的原因是它可以检测到文本溢出页面时,因此他们使用该信息创建具有另一个富文本框的新页面,直到不再发生溢出。无论如何,您都可以使用自己的字符串解析器将文本拆分成不同的页面。基本上,在Windows 8应用程序中打印将打印您想要的任何UIElement,因此您几乎可以通过XAML对齐页面并以与任何其他Windows应用程序相同的方式进行样式设置。真的,请查看问题,这将是很大的帮助。我花了几个小时将PrintSample缩小到最简单的情况,直到我弄清楚了所有工作原理。重复造轮子没有意义,利用我的挣扎来获得优势,这就是Stack的全部意义。干杯!

编辑:为了方便起见,我将在此处发布代码。

步骤1:将此代码添加到带有文本框的页面中。

        protected PrintDocument printDocument = null;
        protected IPrintDocumentSource printDocumentSource = null;
        internal List<UIElement> printPreviewElements = new List<UIElement>();
        protected event EventHandler pagesCreated;

        protected void PrintTaskRequested(PrintManager sender, PrintTaskRequestedEventArgs e)
        {
            PrintTask printTask = null;
            printTask = e.Request.CreatePrintTask("C# Printing SDK Sample", sourceRequested =>
            {
                printTask.Completed += async (s, args) =>
                {
                    if (args.Completion == PrintTaskCompletion.Failed)
                    {
                        await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () =>
                        {
                            MessageDialog dialog = new MessageDialog("Something went wrong while trying to print. Please try again.");
                            await dialog.ShowAsync();
                        });
                    }
                };
                sourceRequested.SetSource(printDocumentSource);
            });
        }

        protected void RegisterForPrinting()
        {
            printDocument = new PrintDocument();
            printDocumentSource = printDocument.DocumentSource;
            printDocument.Paginate += CreatePrintPreviewPages;
            printDocument.GetPreviewPage += GetPrintPreviewPage;
            printDocument.AddPages += AddPrintPages;
            PrintManager printMan = PrintManager.GetForCurrentView();
            printMan.PrintTaskRequested += PrintTaskRequested;
        }

        protected void UnregisterForPrinting()
        {
            if (printDocument != null)
            {
                printDocument.Paginate -= CreatePrintPreviewPages;
                printDocument.GetPreviewPage -= GetPrintPreviewPage;
                printDocument.AddPages -= AddPrintPages;
                PrintManager printMan = PrintManager.GetForCurrentView();
                printMan.PrintTaskRequested -= PrintTaskRequested;
            }
        }

        protected void CreatePrintPreviewPages(object sender, PaginateEventArgs e)
        {
            printPreviewElements.Clear();
            PrintTaskOptions printingOptions = ((PrintTaskOptions)e.PrintTaskOptions);
            PrintPageDescription pageDescription = printingOptions.GetPageDescription(0);
            AddOnePrintPreviewPage(pageDescription);
            if (pagesCreated != null)
            {
                pagesCreated.Invoke(printPreviewElements, null);
            }
            ((PrintDocument)sender).SetPreviewPageCount(printPreviewElements.Count, PreviewPageCountType.Intermediate);
        }

        protected void GetPrintPreviewPage(object sender, GetPreviewPageEventArgs e)
        {
            ((PrintDocument)sender).SetPreviewPage(e.PageNumber, printPreviewElements[e.PageNumber - 1]);
        }

        protected void AddPrintPages(object sender, AddPagesEventArgs e)
        {
            foreach (UIElement element in printPreviewElements)
            {
                printDocument.AddPage(element);
            }
            ((PrintDocument)sender).AddPagesComplete();
        }

        protected void AddOnePrintPreviewPage(PrintPageDescription printPageDescription)
        {
            TextBlock block = new TextBlock();
            block.Text = "This is an example.";
            block.Width = printPageDescription.PageSize.Width;
            block.Height = printPageDescription.PageSize.Height;
            printPreviewElements.Add(block);
        }
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            RegisterForPrinting();
        }

        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
            UnregisterForPrinting();
        }

步骤2:将block.Text替换为您想要的文本。

步骤3:使用打印按钮显示打印界面:

        private async void PrintDocument(object sender, RoutedEventArgs e)
        {
            await Windows.Graphics.Printing.PrintManager.ShowPrintUIAsync();
        }

第四步:将 RequestedTheme="Light" 放入你的 App.xaml 中,然后就完成了。注意:你也可以在这个 XAML 类中以另一种方式设置文本框样式,而不需要设置整个应用程序的主题。

第五步(稍后):你可能想考虑添加自己的新页面检测逻辑,以保持调用顶部的那个方法来创建一个新页面。

第六步(现在):与 M$ 上负责让我们挣扎的人发生冲突。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接