Print html document from Windows Service without print dialog

让人想犯罪 __ 提交于 2019-11-27 04:16:18

First off, here's the code:

using System.Reflection;
using System.Threading;
using SHDocVw;

namespace HTMLPrinting
{
  public class HTMLPrinter
  {
    private bool documentLoaded;
    private bool documentPrinted;

    private void ie_DocumentComplete(object pDisp, ref object URL)
    {
      documentLoaded = true;
    }

    private void ie_PrintTemplateTeardown(object pDisp)
    {
      documentPrinted = true;
    }

    public void Print(string htmlFilename)
    {
      documentLoaded = false;
      documentPrinted = false;

      InternetExplorer ie = new InternetExplorerClass();
      ie.DocumentComplete += new DWebBrowserEvents2_DocumentCompleteEventHandler(ie_DocumentComplete);
      ie.PrintTemplateTeardown += new DWebBrowserEvents2_PrintTemplateTeardownEventHandler(ie_PrintTemplateTeardown);

      object missing = Missing.Value;

      ie.Navigate(htmlFilename, ref missing, ref missing, ref missing, ref missing);
      while (!documentLoaded && ie.QueryStatusWB(OLECMDID.OLECMDID_PRINT) != OLECMDF.OLECMDF_ENABLED)
        Thread.Sleep(100);

      ie.ExecWB(OLECMDID.OLECMDID_PRINT, OLECMDEXECOPT.OLECMDEXECOPT_DONTPROMPTUSER, ref missing, ref missing);
      while (!documentPrinted)
        Thread.Sleep(100);

      ie.DocumentComplete -= ie_DocumentComplete;
      ie.PrintTemplateTeardown -= ie_PrintTemplateTeardown;
      ie.Quit();
    }
  }
}
  1. You can access the SHDocVw namespace by adding a reference to 'Microsoft Internet Controls', found on the COM tab of the Add Reference dialog.
  2. More information on the InternetExplorer object can be found on MSDN.
  3. The Navigate() method will load the HTML file. The other parameters allow you to specify optional parameters, such as flags and headers.
  4. We can't print until the document is loaded. Here, I enter a loop waiting until the DocumentComplete event is called, upon which a flag is set notifying us that navigation has completed. Note that DocumentComplete is called whenever navigation is finished - upon success or failure.
  5. Once the documentLoaded flag is set, the printing status is queried via QueryStatusWB() until printing is enabled.
  6. Printing is started with the ExecWB() call. The OLECMDID_PRINT command is specified, along with the option OLECMDEXECOPT_DONTPROMPTUSER to automatically print without user interaction. An important note is that this will print to the default printer. To specify a printer, you will have to set the default printer (in code, you could call SetDefaultPrinter()). The two final parameters allow optional input and output parameters.
  7. We don't want to quit until printing is complete, so once again a loop is entered. After the PrintTemplateTeardown event is fired, the documentPrinted flag is set. The objects can then be cleaned up.

From this site http://www.ussbd.com/printhtm.html

using HtmlPrinter;
hpObj=new HtmlPrinter.HtmlPrinter();
hpObj.PrintUrlFromMemory(txtUrl.Text);

Now you add the code in your project to print html page from its source text:

HtmlPrinter.HtmlPrinter hpObj=new HtmlPrinter.HtmlPrinter();
hpObj.PrintHtml(txtString.Text, true);

If you want to print without the print dialog then use the following line:

hpObj.PrintHtml(txtString.Text, false); 
blak3r

Here's another way to print without a print dialog. You create a PrintDialog object, initialize it and then call the Print() method.

The function below is used to print a small 2"x0.75" barcode label. You'll need to figure out a way to get an Document object from the html file.

public void PrintToPrinter(string printerName)
{
    PrintDialog pd = new PrintDialog();
    pd.Document = userControl11.PrintDoc; // <--- Update this line with your doc
    pd.PrinterSettings.PrinterName = printerName;
    try
    {
            pd.Document.DocumentName = "My Label";
            pd.Document.DefaultPageSettings.PaperSize = new System.Drawing.Printing.PaperSize("2-.75", 200, 75);
            pd.Document.DefaultPageSettings.Margins = new System.Drawing.Printing.Margins(0, 0, 0, 0);
            //pd.PrinterSettings.Copies = (short)mNumCopies;
            pd.Document.PrinterSettings.Copies = (short) mNumCopies;
            pd.Document.Print();
    }
    catch
    {
        MessageBox.Show("INVALID PRINTER SPECIFIED");
    }
}

You can use the PrintDocument class in the System.Drawing.Printing namespace to give you more control over the printing, see here for more info.

For example you can do the following:

using (PrintDocument doc = new PrintDocument())
{
    doc.PrintPage += this.Doc_PrintPage;
    doc.DefaultPageSettings.Landscape = true;
    doc.DocumentName = fileNameOfYourDocument;
    doc.Print();
}

Then a function is raised for each page to be printed and you are given a Graphics area to draw to

private void Doc_PrintPage(object sender, PrintPageEventArgs ev)
{
    ....
    ev.Graphics.DrawImage(image, x, y, newWidth, newHeight);
}

This does require you handle the actual drawing on the text/image to the page, see here for more info.

OLECMDEXECOPT_PROMPTUSER seems to force a prompt to the user to select printer and all associated stuff, which I am pretty sure is not allowed from a service. Can someone verify this?

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!