Learn how easy it is to sync an existing GitHub or Google Code repo to a SourceForge project! See Demo

Close

Printing with JWebBrowser

Help
2010-12-10
2013-01-27
  • Andres Ederra
    Andres Ederra
    2010-12-10

    Hi All,

    Just some fedback about how to enable printing of the content of a JWebBroser.

    First some references of other discussions related with this same issue:

    [https://sourceforge.net/projects/djproject/forums/forum/671154/topic/3507535]
    (https://sourceforge.net/projects/djproject/forums/forum/671154/topic/3507535)
    https://bugs.eclipse.org/bugs/show_bug.cgi?id=44823

    Now, lets say we have a JWebBrowser and we want to print its content.
    The first aproach could be to execute some javascript as "print();" sent from
    our java code to the JWebBrowser. This works in some scenarios, but in others
    it doesn't, for instance if we have a JWebBrowser(IE based) showing a pdf
    document, javascript print wont work as there is no proper html page loaded...
    (when using mozilla, at lest mozilla/win/32 bits, javascript print works even
    when a html page is not loaded)

    So a the second aproach that works in this case (and in all others as far as I
    know) is to use the Ole API exposed in the IE Browser.
    Unfortunately we'll need acces to the non public class
    "org.eclipse.swt.browser.IE" and its private attribute "auto"... but access
    protection in java could be considered just _informative _if we cheat it with
    reflection ( I know this is ugly... very ugly...).

    So applying these modifications to
    chrriis.dj.nativeswing.swtimpl.components.JWebBrowser and
    chrriis.dj.nativeswing.swtimpl.components.NativeWebBrowser printing could be
    implemented (If you dont want to modify DJ code you can implemnt it on your
    code too adding even more access protection cheating...)

    And last, the bravest of the bravest all this reflection cheating could be
    omited but it requires modifications not only on DJ Native Swing but on SWT
    too

    So here comes the changes:

    Add this print method to JWebBrowser:

      public void print(boolean showDialog) {
          nativeWebBrowser.print(showDialog);
      }
    

    And add this method and class to NativeWebBrowser:

    public void print(boolean showDialog) {
        runAsync(new CMN_print(),showDialog);
      }
    
      private static class CMN_print extends ControlCommandMessage {
          @Override
          public Object run(Object[] args) {
    
              boolean showStdSetupDialog = true;
    
              if(args.length>0)
                  showStdSetupDialog=(Boolean) args[0];
    
              OleAutomation swtBrowserAutomation = null;
    
              Object swtWebBrowser=null;
    
              Browser swtBrowser=null;
    
              try {
                  swtBrowser = (Browser) getControl();
    
                  swtWebBrowser=bypassAttribute(swtBrowser.getClass(), swtBrowser, "webBrowser");
    
                  Class IEClass=Class.forName("org.eclipse.swt.browser.IE");
    
                  if (IEClass.isInstance(swtWebBrowser)) {
                      swtBrowserAutomation=(org.eclipse.swt.ole.win32.OleAutomation) bypassAttribute(IEClass, swtWebBrowser, "auto");
                  }
              } catch (Exception e) {
                  //OK, IE cannot be found, so we fallback to javascript printing
              }
    
              if (swtBrowserAutomation == null) {
                  swtBrowser.execute("print();");
              } else {
                     int[] rgdispid = swtBrowserAutomation.getIDsOfNames(new String[] {
                          "ExecWB", "cmdID", "cmdexecopt" });
                  Variant[] rgvarg = new Variant[2];
    
                  // OLECMDID_PRINT is const from MS headers
                  rgvarg[0] = new Variant(OLE.OLECMDID_PRINT);
    
                  // OLECMDEXECOPT_PROMPTUSER = 1
                  // OLECMDEXECOPT_DONTPROMPTUSER = 2
                  rgvarg[1] = new Variant(showStdSetupDialog ? 1 : 2);
    
                  int[] rgdispidNamedArgs = new int[2];
                  rgdispidNamedArgs[0] = rgdispid[1];
                  rgdispidNamedArgs[1] = rgdispid[2];
                  Variant pVarResult = swtBrowserAutomation.invoke(rgdispid[0],
                          rgvarg, rgdispidNamedArgs);
    
              }
    
            return null;
          }
    
          private Object bypassAttribute(Class className, Object instance, String attributeName){
    
              Field field;
    
              Object value = null;
    
              try {
                  field = className.getDeclaredField(attributeName);
                  field.setAccessible(true);
                  value =  field.get(instance);
              } catch (Exception e) {
                  e.printStackTrace();
              }
    
              return value;
          }
        }
    

    Enjoy your printing

     
  • Hi,

    This is very interesting because this issue comes up regularly. Thanks a lot
    for the contribution!

    Now I wonder if there is any way that I could expose this functionality as
    part of the code, which one would activate knowingly that it may not work in
    the future (this is highly dependant on how SWT is implemented).

    I will think about it and if I do anything I will let you know. Of course if
    you have some interesting ideas, please share!

    Cheers,
    -Christopher

     
  • Hi Andres,

    I just uploaded a new 0.9.9 preview version which adds the following method:
    public boolean JWebBrowser.print(boolean isShowingDialog);

    The idea is that if you want batch printing and the runtime does not support
    it (at the moment only IE supports it), then it would return false. If
    something goes wrong, it should also return false.

    Thanks a lot for your contribution, and if you get to play with that version,
    please let me know what you think!

    -Christopher

     
  • PAULUS
    PAULUS
    2013-01-21

    This is an older topic, but exactly what I am working on and struggling with...

    I am using version 1.0.2 and the method JWebBrowser.print(boolean isShowingDialog) prints the HTML content very nicely! However, I can't seem to get it to automatically print to the specific printer I want it to go to, that's not the default one.

    I've tried a bunch of different approaches, none of which have been successful. I'm not sure if it's possible with the current way JWebBrowser.print(boolean isShowingDialog) is implemented, but I just wanted to check.

    If you can provide any insight on how I can get the printing of JWebBrowser.print(boolean isShowingDialog) to be able to go to the printer of my choosing, I would be most grateful!

    Thanks!

     
  • Hi Paulus,

    Printing without a dialog is currently supported on IE only. This feature uses OLE to perform the printing operation, and there is currently no way to specify the default printer. I have no idea if OLE printing has a way to specify it.

    About what you are trying to do: isn't it the point to print to the default printer when you don't want a dialog, and to show the dialog when you don't want the default printer? :)

    -Christopher