如何使用PrintDocument在热敏打印机上打印文本文件?

我正在使用带有Winforms的C#创建一个应用程序,现在我需要在热敏打印机上打印销售收据。 要做到这一点,我正在创建一个文本文件,并使用PrintDocument读取它进行打印,但我不能这样做,因为我不知道如何配置纸张大小,在纸张上对齐文本中心,以及其他配置。 当我打印文本文件被打印,但所有杂乱,并在结束打印后纸张没有停止。

我怎么能这样做?

试。

 private PrintDocument printDocument = new PrintDocument(); private static String RECEIPT = Environment.CurrentDirectory + @"\comprovantes\comprovante.txt"; private String stringToPrint = ""; private void button1_Click(object sender, EventArgs e) { generateReceipt(); printReceipt(); } private void generateReceipt() { FileStream fs = new FileStream(COMPROVANTE, FileMode.Create); StreamWriter writer = new StreamWriter(fs); writer.WriteLine("=========================================="); writer.WriteLine(" NOME DA EMPRESA AQUI "); writer.WriteLine("=========================================="); writer.Close(); fs.Close(); } private void printReceipt() { FileStream fs = new FileStream(COMPROVANTE, FileMode.Open); StreamReader sr = new StreamReader(fs); stringToPrint = sr.ReadToEnd(); printDocument.PrinterSettings.PrinterName = DefaultPrinter.GetDefaultPrinterName(); printDocument.PrintPage += new PrintPageEventHandler(printPage); printDocument.Print(); sr.Close(); fs.Close(); } private void printPage(object sender, PrintPageEventArgs e) { int charactersOnPage = 0; int linesPerPage = 0; Graphics graphics = e.Graphics; // Sets the value of charactersOnPage to the number of characters // of stringToPrint that will fit within the bounds of the page. graphics.MeasureString(stringToPrint, this.Font, e.MarginBounds.Size, StringFormat.GenericTypographic, out charactersOnPage, out linesPerPage); // Draws the string within the bounds of the page graphics.DrawString(stringToPrint, this.Font, Brushes.Black, e.MarginBounds, StringFormat.GenericTypographic); // Remove the portion of the string that has been printed. stringToPrint = stringToPrint.Substring(charactersOnPage); // Check to see if more pages are to be printed. e.HasMorePages = (stringToPrint.Length > 0); } 

我正在尝试创建这种收据模式。

在此处输入图像描述

使用RDLC,但开始打印速度很慢 。 我跟着这个例子

 //works but slow private void Run() { LocalReport report = new LocalReport(); report.ReportPath = @"..\..\reports\ReciboDeVenda.rdlc"; Export(report); Print(); } private void Export(LocalReport report) { string deviceInfo = @" EMF 8.5in 11in 0.25in 0.25in 0.25in 0.25in "; Warning[] warnings; m_streams = new List(); report.Render("Image", deviceInfo, CreateStream, out warnings); foreach (Stream stream in m_streams) stream.Position = 0; } private Stream CreateStream(string name, string fileNameExtension, Encoding encoding, string mimeType, bool willSeek) { Stream stream = new MemoryStream(); m_streams.Add(stream); return stream; } private void Print() { if (m_streams == null || m_streams.Count == 0) throw new Exception("Error: no stream to print."); PrintDocument printDoc = new PrintDocument(); printDoc.PrinterSettings.PrinterName = DefaultPrinter.GetDefaultPrinterName(); if (!printDoc.PrinterSettings.IsValid) { throw new Exception("Error: cannot find the default printer."); }else { printDoc.PrintPage += new PrintPageEventHandler(PrintPage); m_currentPageIndex = 0; printDoc.Print(); } } private void PrintPage(object sender, PrintPageEventArgs ev) { Metafile pageImage = new Metafile(m_streams[m_currentPageIndex]); // Adjust rectangular area with printer margins. Rectangle adjustedRect = new Rectangle( ev.PageBounds.Left - (int)ev.PageSettings.HardMarginX, ev.PageBounds.Top - (int)ev.PageSettings.HardMarginY, ev.PageBounds.Width, ev.PageBounds.Height); // Draw a white background for the report ev.Graphics.FillRectangle(Brushes.White, adjustedRect); // Draw the report content ev.Graphics.DrawImage(pageImage, adjustedRect); // Prepare for the next page. Make sure we haven't hit the end. m_currentPageIndex++; ev.HasMorePages = (m_currentPageIndex < m_streams.Count); } 

如果你向printPage(object sender, PrintEventArgs e)方法发送一个普通的字符串,它只会打印所有相同字体的纯文本,看起来很“杂乱”(如你printPage(object sender, PrintEventArgs e) )如果你想要打印好格式化的不同的字体(粗体,常规),您必须手动完成所有操作:

 List itemList = new List() { "201", //fill from somewhere in your code "202" }; private void printPage( object sender, PrintPageEventArgs e ) { Graphics graphics = e.Graphics; Font regular = new Font( FontFamily.GenericSansSerif, 10.0f, FontStyle.Regular ); Font bold = new Font( FontFamily.GenericSansSerif, 10.0f, FontStyle.Bold ); //print header graphics.DrawString( "FERREIRA MATERIALS PARA CONSTRUCAO LTDA", bold, Brushes.Black, 20, 10 ); graphics.DrawString( "EST ENGENHEIRO MARCILAC, 116, SAO PAOLO - SP", regular, Brushes.Black, 30, 30 ); graphics.DrawString( "Telefone: (11)5921-3826", regular, Brushes.Black, 110, 50 ); graphics.DrawLine( Pens.Black, 80, 70, 320, 70 ); graphics.DrawString( "CUPOM NAO FISCAL", bold, Brushes.Black, 110, 80 ); graphics.DrawLine( Pens.Black, 80, 100, 320, 100 ); //print items graphics.DrawString( "COD | DESCRICAO | QTY | X | Vir Unit | Vir Total |", bold, Brushes.Black, 10, 120 ); graphics.DrawLine( Pens.Black, 10, 140, 430, 140 ); for( int i = 0; i < itemList.Count; i++ ) { graphics.DrawString( itemList[i].ToString(), regular, Brushes.Black, 20, 150 + i * 20 ); } //print footer //... regular.Dispose(); bold.Dispose(); // Check to see if more pages are to be printed. e.HasMorePages = ( itemList.Count > 20 ); } 

我的例子可能有所改进:

  • 使用graphics.MeasureString()可以更好地对标题字符串进行居中。
  • 项目列表最好是一个普通字符串的业务类列表

因为这一切都很多,所以您应该考虑使用RDLC或某些第三方软件来设计您的文档。

如果我想自己创建一个报告,而不是尝试创建一个文本文件,我将使用HTML进行渲染。 另外,为了使渲染逻辑和混合html标签和数据更简单,我使用T4运行时文本模板 。 然后我可以将数据传递给html模板并简单地呈现报告。 然后将输出字符串分配给WebBrowserDocumentText属性并调用其Print方法就足够了。

下载

您可以从r-aghaei / HtmlUsingRuntimeT4克隆或下载工作示例

为何选择HTML?

由于格式简单灵活。 您可以使用html标签和CSS样式的所有function来格式化文本。 它比使用DrawString更好。

为什么选择运行时文本模板?

因为它使混合数据和html非常容易,你可以使用C#语言执行一些任务,如计算总和,迭代模型记录等等。 它使用T4模板引擎,允许您在运行时使用模板并将数据提供给模板。

1-向项目添加模型:

 using System; using System.Collections.Generic; namespace Sample { public class ReportModel { public string CustomerName { get; set; } public DateTime Date { get; set; } public List OrderItems { get; set; } } public class OrderItem { public string Name { get; set; } public int Price { get; set; } public int Count { get; set; } } } 

2-将运行时文本模板(也称为预处理文本模板)添加到项目中,并将其命名为ReportTemplate.tt 。 打开它并添加这样的代码:

 <#@ template language="C#"#> <#@ import namespace="System.Linq" #> <#@ import namespace="System.Collections.Generic" #> <#@ parameter name="Model" type="Sample.ReportModel"#>       

Order


Customer: <#=Model.CustomerName#> Order Date: <#=Model.Date#>

<# int index =1; foreach(var item in Model.OrderItems) { #> <# index++; } var total= Model.OrderItems.Sum(x=>x.Count * x.Price); #>
IndexNamePriceCountSum
<#=index#> <#=item.Name#> <#=item.Price#> <#=item.Count#> <#=item.Count * item.Price#>
Total:<#=total#>

3-将WebBrowser控件放在表单上,​​并在要生成报表的位置编写此类代码:

 var rpt = new ReportTemplate(); rpt.Session = new Dictionary(); rpt.Session["Model"] = new Sample.ReportModel { CustomerName = "Reza", Date = DateTime.Now, OrderItems = new List() { new Sample.OrderItem(){Name="Product 1", Price =100, Count=2 }, new Sample.OrderItem(){Name="Product 2", Price =200, Count=3 }, new Sample.OrderItem(){Name="Product 3", Price =50, Count=1 }, } }; rpt.Initialize(); this.webBrowser1.DocumentText= rpt.TransformText(); 

4-如果要打印报告,可以致电:

 this.webBrowser1.Print(); 

您应该在文档完成后调用Print 。 因此,如果您想直接打印而不向用户显示输出,您可以处理DocumentCompleted事件并在那里调用Print

结果如下:

在此处输入图像描述

您的热敏打印机是否支持OPOS?

如果是这样,我建议您尝试使用Microsoft Point of Service