title: How to print a text file on thermal printer using PrintDocument?
body: <p>I'm creating an application using C# with Winforms and now I need to print the receipt of sale on a thermal printer. To do this I'm creating a text file and reading it to print using the <code>PrintDocument</code>  but I cannot do this because I don't know how to configure paper size, align text center on the paper, and others configurations. When I do print the text file is printed, but all messy, and after the end print the paper isn't stopping.</p>
  
  <p>How could I do this ?</p>
  
  <p>trying.</p>
  
  <pre><code>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 &gt; 0);
  }
  </code></pre>
  
  <p><strong>I'm trying create this model of receipt.</strong></p>
  
  <p><a href="https://i.stack.imgur.com/aNevI.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/aNevI.png" alt="enter image description here"></a></p>
  
  <p><strong>Using RDLC, but it is very slow to start print</strong>. I'm follow this <a href="https://msdn.microsoft.com/en-us/library/ms252091.aspx" rel="nofollow noreferrer">example</a></p>
  
  <pre><code>//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 =
        @"&lt;DeviceInfo&gt;
          &lt;OutputFormat&gt;EMF&lt;/OutputFormat&gt;
          &lt;PageWidth&gt;8.5in&lt;/PageWidth&gt;
          &lt;PageHeight&gt;11in&lt;/PageHeight&gt;
          &lt;MarginTop&gt;0.25in&lt;/MarginTop&gt;
          &lt;MarginLeft&gt;0.25in&lt;/MarginLeft&gt;
          &lt;MarginRight&gt;0.25in&lt;/MarginRight&gt;
          &lt;MarginBottom&gt;0.25in&lt;/MarginBottom&gt;
      &lt;/DeviceInfo&gt;";
      Warning[] warnings;
      m_streams = new List&lt;Stream&gt;();
      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 &lt; m_streams.Count);
  }
  </code></pre>