Results 1 to 3 of 3

Thread: WPF Printing HTML

  1. #1

    Thread Starter
    Lively Member
    Join Date
    Mar 2016
    Posts
    106

    WPF Printing HTML

    Good Morning,

    I am new to programming. I have created this file viewer program that launches when it receives a command line call from a legacy program. The legacy application gives it a network path to a file and my VB application loads it into a viewer.

    For HTML files, I have a WebBrowser control that displays the file and that works nicely. There is a combobox that loads the user's printers and a print button so that the user can select a printer and print the content.

    The printing part is where it all goes wrong. I have been reading all over trying to figure out how people do this. There is probably alot of things I am not understanding, but it appears that printing HTML with WPF is maybe incomplete and so there are all these sort of rig job solutions. I selected WPF for my application because I got the impression that this is what everything is going to in the future over Windows Forms.

    So I understand that I cant just print an HTML file. The code has to be read and rendered by a program like a web browser first. Otherwise the printer just prints the html code.

    In windows forms, the web browser control has a webbrowser.print method. This method is absent from the WPF webbrowser control/class. What people do to get around this is load the webbrowser.document property into mshtml.IHTMLDocument2 which has the execCommand function which works like process.start()

    Code:
    Dim browser As New WebBrowser()
                    Dim htmlPage As mshtml.IHTMLDocument2
                    htmlPage = browser.Document
                    htmlPage.execCommand("Print", True)
    This does work, but I dont want the printer chooser dialog to show as my users have already selected their printer from the drop down provided. ExecCommand also lacks a "PrintTo" verb so that I can designate a printer to print to...(which is probably why I cannot hide the printer chooser dialog). I also dont think I have any way to control the printjob like setting margins and boundaries like you can with system.drawing.printing stuff like printersettings and printdocument.

    So I was taking a look at Merrion's "A Beginner's Guide To Printing .NET" on this forum.
    http://www.vbforums.com/showthread.p...light=printing
    This is a very cool writeup. I think I need to take more manual control of printing in my application. Will this guide work for printing HTML content?

    I dont think I quite understand the relationship between Events, withevents, handles. Also, there seems to be a flow of events like begin print event and onpage event and printcomplete event. Where is a good place to go to learn more about events/handles?

    Should I just rewrite my program with windows forms instead?

    I hope what I wrote makes sense.

  2. #2
    Super Moderator si_the_geek's Avatar
    Join Date
    Jul 2002
    Location
    Bristol, UK
    Posts
    41,930

    Re: WPF Printing HTML

    Quote Originally Posted by leadhead View Post
    So I was taking a look at Merrion's "A Beginner's Guide To Printing .NET" on this forum.
    http://www.vbforums.com/showthread.p...light=printing
    This is a very cool writeup. I think I need to take more manual control of printing in my application. Will this guide work for printing HTML content?
    Sort of, but I would expect it to be a very large amount of work...
    Should I just rewrite my program with windows forms instead?
    I've never had the need to print HTML from WPF, but it sounds like you've researched this well, and this is probably one of those rough edges we sometimes find.

    A re-write is one option, and for this specific thing I expect it would be much easier... but you'd then lose the features of WPF in the other parts of your application (as as WPF has lots of nice features, I wouldn't recommend that).

    What you could do is create another program for just this specific part of the system, and call it from the appropriate point. You could do it as an executable you call via the command line, or you could make a DLL (the executable is probably easier).

    I dont think I quite understand the relationship between Events, withevents, handles. Also, there seems to be a flow of events like begin print event and onpage event and printcomplete event. Where is a good place to go to learn more about events/handles?
    An Event is a sub/function which gets run automatically in response to something happening (eg: the user clicked on a button).

    The Handles section simply links the sub/function to the Event. If you want to, you can write one sub/function that will be called for multiple events, by simply adding extra items to the Handles section (eg: you could change "Handles Button1.Click" to "Handles Button1.Click, Button2.Click" so it gets called for both - and you can use the Sender parameter to work out which).

    When you create a form (or put controls on it, etc) the events are set up for you... but when you create variables that doesn't happen. Using WithEvents when declaring a variable is the way to say that it should be allowed to cause Events.

  3. #3

    Thread Starter
    Lively Member
    Join Date
    Mar 2016
    Posts
    106

    Re: WPF Printing HTML

    Thanks so much for the response. Good point, sticking with WPF is the right choice. I guess it would be helpful to share my process so far if anyone runs into something similar.

    Firstly html printing from a file that you are loading into your browser control is best and most easily done by downloading and installing on the application machine, Microsoft's DHTML editing component. Then you can incorporate this PrintHTML program http://www.printhtml.com/ to send jobs discretely to whatever printer that client machine may have installed by using process start like so.

    Code:
            Dim appPath As String = System.AppDomain.CurrentDomain.BaseDirectory
            Dim file As String = appPath & "printhtml.exe"
            Dim arguments As String = ("file=" & fileName & " " & "printername=" & ControlChars.Quote & printer & ControlChars.Quote)
            Dim p As New Process()
            Dim pi As New ProcessStartInfo()
            pi.WindowStyle = ProcessWindowStyle.Hidden
            pi.Arguments = arguments
            pi.FileName = (file)
            p.StartInfo = pi
            p.Start()
    So in my case, I can load all the printers into a combo box and then the user can select the desired printer and click the print button. This still doesnt allow you the control of the print job like the print document class does where you can use for example system.drawing.graphics to draw the pictures and set page bounds, margins and so on. I do this when printing tiff files from the tiff viewer portion of my application.

    Unfortunately, my application needs to be portable.

    For a browser control, I messed around with a bunch of them. I even used the windows forms browser that I attached as a child programmatically to a windows forms host control. This worked nicely and while I have conceded to just get rid of my printer combobox selector and use the browser dialog popup when printing, the windows webbrowser wont display PDFs natively, you must have adobe acrobat installed. In my environment, adobe reader might not be installed.

    Alternative browsers that I experimented with that work really well are CefSharp. This had much nicer scrolling and was very snappy. It also has the browser.print() capability. However, while this browser does have the nice google chrome pdf viewer embedded, there seems to be bugs with it...or probably a better explanation would be that I am not a good enough programmer to write the proper code to tease the browser control to get it to work correctly. The pdf viewer would flicker and do all sorts of funny stuff.

    Another good browser control is Awesomium. This one does everything well except it doesnt expose a print function from the control except to PDF to which I am printing over the network and my html file has links to images stored in other network locations. So an 18k HTML file turns into a 200 meg PDF that has to be pulled over the network, converted, saved to disk and then printed....its slow.


    I didnt really dive into gecko (mozilla) browsers because my application runs on an RDS server. Firefox type browsers seem to initialize with a couple hundred megs of memory most times whether they need it or not and ramp up that usage rapidly.

    Well when you have 30+ people on that server with multiple instances of browser/file displays, it eats a ton of memory. Chrome browsers seem to be much much more efficient.


    Awesomium has other components like the IWebViewPresenter
    Code:
    WebViewPresenter
    
    Used when ViewType is set to Offscreen (default). This is an ISurface component that uses 100% WPF logic to copy the view's pixel buffer to a bitmap that it then renders for presentation.
    
    WebViewPresenter inherits FrameworkElement and is part of the WPF WebControl's default style. When the visual tree is loaded for presentation, the WPF WebControl uses the IWebViewPresenter interface to communicate with the WebViewPresenter that takes care of all UI related operations which besides rendering include:
    
    Handling user input
    Presentation of dialogs
    Presentation of menus
    PIXEL BUFFER
    The WebViewPresenter exposes an Image property which represents the WPF ImageSource wrapping the pixel buffer currently rendered by the surface. Users can use this image to either save a snapshot on disk, or create mirror presentations of the view.
    
    For an example, see: Getting a snapshot using the WPF WebControl.
    
    USER INPUT
    It is important to note that in WPF, it is the WebViewPresenter and not the WebControl itself that handles user input. This means that handling user input related events on the WebControl, will not prevent the WebViewPresenter from handling these events and passing them to the native view.
    
    Since the WebViewPresenter is part of the WebControl's visual tree, the appropriate way to handle such events yourself, is by handling the Preview events.
    
    Native windowed views handle user input themselves and there's no way to handle or simulate user input on the managed side. If you need to handle or simulate user input, make sure that WebControl.ViewType is set to Offscreen (default).
    For an example, see: Handling or Simulating User Input with the WPF WebControl.
    which does print, but its for the user interaction (CTRL + P). I tried to think of any way possible to transfer/convert/cast the contents of my browser object into this so that I could print.

    Windows Forms has the sendkeys methods to emulate a user interaction like (CTRL + P) unfortunately this (of course it hasnt!) hasnt been invented for WPF! So it appears the only way to access the print function of iwebpresenter.print() is to automate it with javascript.

    Does anyone know how to do this?


    But basically my boss wants a portable client that prints files from a server and called from a mapped drive to that server while still performing at the same level as the locally installed PC applications that this new app is designed to replace.

    I have only been doing this for 6 months LOL no problem boss!

    I have a tiff viewer on a stack panel that I hide when I am displaying HTML and vise versa when I am displaying tiffs. I could also add a pdf viewer control in another stack panel...add it to the others. I didnt really understand how to get adobe reader's SDK to work, I also didnt see any PDF viewer code out there that would just display and print PDFs without shelling out 11ty billion dollars.

    Do you guys have any ideas?
    Last edited by leadhead; Jul 25th, 2016 at 12:48 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width