File HTML di stampa silenziosa in C # usando WPF

EDIT: completamente riscritto domanda e aggiunto taglie.

Sulla base di molte esercitazioni e domande StackOverflow posso ora:

  • Stampa più pagine insieme come un unico documento.
  • Stampa il contenuto attuale.
  • Allinea correttamente il contenuto alla pagina.
  • Stampa documenti di dimensioni corrette.

La soluzione richiede che il documento HTML abbia dello spazio bianco nella parte inferiore e il tag di stile html {overflow: hidden; } – per hide le barre di scorrimento e per consentire lo scorrimento per essere utilizzato per l’impaginazione – ma posso accettarlo.

L’unico problema rimanente è che WPF non rende le parti del browser che non sono sullo schermo.

Ciò significa che se si inclina lo schermo del computer posso stampare correttamente, ma se non lo faccio il documento taglia la parte inferiore.

Ho provato il rendering in una bitmap, ma quando stampo l’immagine risultante come immagine visiva le pagine sono vuote.

Se sai come forzare WPF per renderizzare completamente o come renderizzare correttamente in bitmap, per favore aiutami.

Stampa finestra XAML: (la stampa di WPF funziona solo sul thread dell’interfaccia utente, altrimenti non viene eseguito il rendering …)

      

Stampa la finestra code-behind:

 public partial class PrintWindow : Window { public PrintWindow(string path) { InitializeComponent(); FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read); webBrowser.NavigateToStream(fs); ContentRendered += OnContentRendered; } private void OnContentRendered(object sender, EventArgs eventArgs) { PrintDialog pd = new PrintDialog { PrintTicket = new PrintTicket { Duplexing = Duplexing.TwoSidedLongEdge, OutputColor = OutputColor.Monochrome, PageOrientation = PageOrientation.Portrait, PageMediaSize = new PageMediaSize(794, 1122), InputBin = InputBin.AutoSelect } }; //Ok, final TODO: Page only renders what is on the PC screen... WebPaginator paginator = new WebPaginator(webBrowser, 1089, 1122, 794); pd.PrintDocument(paginator, "CustomerLetter"); Close(); } } 

Paginatore personalizzato:

 public class WebPaginator : DocumentPaginator { private readonly WebBrowser webBrowser; private readonly int pageScroll; private Size pageSize; public WebPaginator(WebBrowser webBrowser, int pageScroll, double pageHeight, double pageWidth) { this.webBrowser = webBrowser; this.pageScroll = pageScroll; pageSize = new Size(pageWidth, pageHeight); } public override DocumentPage GetPage(int pageNumber) { HTMLDocument htmlDoc = webBrowser.Document as HTMLDocument; if (htmlDoc != null) htmlDoc.parentWindow.scrollTo(0, pageScroll * pageNumber); Rect area = new Rect(pageSize); return new DocumentPage(webBrowser, pageSize, area, area); } public override bool IsPageCountValid { get { return true; } } ///  /// Returns one less than actual length. /// Last page should be whitespace, used for scrolling. ///  public override int PageCount { get { var doc = (IHTMLDocument2)webBrowser.Document; var height = ((IHTMLElement2)doc.body).scrollHeight; int tempVal = height*10/pageScroll; tempVal = tempVal%10 == 0 ? Math.Max(height/pageScroll, 1) : height/pageScroll + 1; return tempVal > 1 ? tempVal-1 : tempVal; } } public override Size PageSize { get { return pageSize; } set { pageSize = value; } } ///  /// Can be null. ///  public override IDocumentPaginatorSource Source { get { return null; } } } 

È ansible utilizzare la funzione di stampa standard di IE (tramite il metodo ExecWB ), in questo modo:

 public partial class PrintWindow : Window { public PrintWindow() { InitializeComponent(); webBrowser.Navigate("http://www.google.com"); } // I have added a button to demonstrate private void Button_Click(object sender, RoutedEventArgs e) { // NOTE: this works only when the document as been loaded IOleServiceProvider sp = webBrowser.Document as IOleServiceProvider; if (sp != null) { Guid IID_IWebBrowserApp = new Guid("0002DF05-0000-0000-C000-000000000046"); Guid IID_IWebBrowser2 = new Guid("D30C1661-CDAF-11d0-8A3E-00C04FC9E26E"); const int OLECMDID_PRINT = 6; const int OLECMDEXECOPT_DONTPROMPTUSER = 2; dynamic wb; // will be of IWebBrowser2 type, but dynamic is cool sp.QueryService(IID_IWebBrowserApp, IID_IWebBrowser2, out wb); if (wb != null) { // note: this will send to the default printer, if any wb.ExecWB(OLECMDID_PRINT, OLECMDEXECOPT_DONTPROMPTUSER, null, null); } } } [ComImport, Guid("6D5140C1-7436-11CE-8034-00AA006009FA"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] private interface IOleServiceProvider { [PreserveSig] int QueryService([MarshalAs(UnmanagedType.LPStruct)] Guid guidService, [MarshalAs(UnmanagedType.LPStruct)] Guid riid, [MarshalAs(UnmanagedType.IDispatch)] out object ppvObject); } }