Click to return to the DHTML, HTML     
Web Workshop  |  DHTML, HTML & CSS

Scripting Support for Web Page Printing


Andrew "Captain" Cerebrum
Senior Developer
Mead & Company Limited

November 20, 1998

DownloadDownload the source code files (zipped, 6.18K).

Contents
Introduction
Printing and Internet Explorer 5: What's New?
The Internet Explorer 4.x way: WebBrowser Control
Printing-Related Commands
Example One
It's in the Frame
Printing Hidden Content
Print Setup Options

Introduction

In this article, we will talk about ways in which you can implement printing support for your HTML pages viewed using Internet Explorer version 4.0 and later. We will examine Internet Explorer 5's new printing functions, and provide a ready-built JScript™ file that you can include in your pages to provide "backwards compatibility" with those functions in earlier 4. x browsers. We'll also show you some samples that use our print.js file, briefly describe our code (non-techies can skip this bit), and mention some ActiveX control-based ways to customize your page printing settings even further.

Internet Explorer 4.0 introduced a bunch of new and very exciting capabilities for Web application development. Unfortunately, one very important feature was overlooked: printing. There is no Dynamic HTML (DHTML) DOM method available to print a page or modify page settings in Internet Explorer 4. x. With the release of Internet Explorer 5, we see the introduction of some new printing features, so this seems like a good time to demonstrate how to use Internet Explorer 5's native printing support and investigate the possibility of near-100 percent emulation for 4. x browsers.

Printing and Internet Explorer 5: What's New?

Let's start with a brief description of Internet Explorer 5's new printing functions:

window.print()

This method will behave as if the user has chosen the File | Print... menu. It will not be possible for a normal HTML page to start printing without the user interface (UI). This method is Netscape Navigator 4. x compatible, so it does not take any parameters.

window.onbeforeprint

This event cannot be canceled and will not bubble. It will fire only after the document has been fully loaded and the onload events have returned. Printing will not occur until onbeforeprint handlers have been executed.

window.onafterprint

This event cannot be canceled and will not bubble. UI control will not return to the user until the event handler is executed. The event will be called after all the drawing operations have been completed (in other words, after the software's job is done and the printing hardware has taken over).

Setting Event Handlers Without Code

The onbeforeprint and onafterprint event handlers are defined in much the same way as those for the existing onload and onunload events. They can be set using the following attributes:

for <BODY>:

<body
onbeforeprint="beforeprint()"
onafterprint="afterprint()">

for <FRAMESET>:

<frameset onbeforeprint="beforeprint()"
onafterprint="afterprint()">

Or you may assign them at run time:

window.document.onbeforeprint=beforeprint;
window.document.onafterprint=afterprint;
window.onbeforeprint=beforeprint;
window.onafterprint=afterprint;

Code Sample

// This example shows a page that modifies its title before printing
// and then resets it to its original value after printing.
var originalTitle;

<script for=window event=onbeforeprint>
  originalTitle = document.title;
  document.title = document.title + " - by Captain"
</script>

<script for=window event=onafterprint>
  document.title = originalTitle;
</script>

In summary, we can now print from script, we can choose to do something just before we print, and we can make something happen once printing has started. All in all, it's a very welcome development for users of Internet Explorer 5 and later. But how can we generalize printing tasks for both Internet Explorer 4. x and Internet Explorer 5? From here on, we provide the script that uses native printing support if available, and closely emulates it if not.

The Internet Explorer 4. x Way: WebBrowser Control

Developers who create custom browsing applications know about the WebBrowser control. This is the underlying engine that hosts Active Documents (as MSHTML documents) and handles navigation from one document to another. Each page and nested frame has a corresponding WebBrowser object.

Is it Safe?

The WebBrowser control exposes a set of Automation properties that is potentially unsafe, but at first sight that doesn't matter, because there is apparently no reason to place a WebBrowser object onto an HTML page, and anyway the Internet Explorer 4.0 team has done its best to make such a pastime fairly useless (read PRB: Permission Denied Accessing Web Browser Control in HTMLNon-MSDN Online link). However, some clever person -- possibly Steve Gore, although we don't really know who did this first -- came up with the idea of using WebBrowser's Exe cWBNon-MSDN Online linkmethod to initiate the printing of a page.

Where There's a Method ...

In fact, ExecWB is partially documentedNon-MSDN Online link for those who do custom WebBrowser hosting. As it turns out, a stand-alone, non-navigated WebBrowser object can be placed on an HTML page -- in which case it will forward all ExecWBcalls to its parent document.

Printing-Related Commands

WebBrowser is known to support OLECMDID_PRINT(6,1) and OLECMDID_PAGESETUP(8) printing related commands.

Doing the Basics

The trick is to create a temporary WebBrowser object with DHTML and invoke ExecWB(6, 1)on it to print the page, as shown:

document.body.insertAdjacentHTML("beforeEnd",
    "<object id=\"idWBPrint\" width=0 height=0 \

classid=\"clsid:8856F961-340A-11D0-A96B-00C04FD705A2\">
    </object>");
  idWBPrint.ExecWB(6, 1);
  idWBPrint.outerHTML = "";

In real life, we've added error handling to the above code, because ExecWB(6, 1) could fail if a user selected the Cancel button on the print dialog.

Example One

Note: To check out these samples, you must be using Internet Explorer 4.x or Internet Explorer 5.

You can check out the first sample or read on for more details. The JScript printing method is printFrame(frameToPrint). You can also review a description of the code in the print.js file. It uses the new native print support for Internet Explorer 5 and provides emulation for the print() method and the onbeforeprint/onafterprintevents in Internet Explorer 4. x. To use this, simply include our print.js file on your own pages:

<script defer
src="print.js"></script>

Now you can have a single HTML page source for both Internet Explorer 4. x and Internet Explorer 5:

<head>
<title>Simple Printing</title>
<script defer language=JScript
src="print.js"></script>
</head>

<body onbeforeprint="beforeprint()"
onafterprint="afterprint()"
  bgcolor="infobackground">
<p><input disabled name="idPrint" type="button"
  value="Print this page"
onclick="print()"> </p>
</body>

<script defer>
function window.onload() {
  idPrint.disabled = false;
}

var originalTitle;
function beforeprint() {
  idPrint.disabled = true;
  originalTitle = document.title;
  document.title = originalTitle + " - by Captain";
}

function afterprint() {
  document.title = originalTitle;
  idPrint.disabled = false;
}
</script>

Note that we have Internet Explorer 4. x support only for <BODY> inline assigned event handlers. Not perfect, but we think this is probably enough to maintain the same code for both Internet Explorer 4. x and Internet Explorer 5. Notice how, in the sample code above, we are updating the title of the document at print time.

It's in the Frame

We also want to be able to print a specific frame, probably from another frame. Or we might need to print a window's content from inside a frame. Luckily, WebBrowser prints the frame that has the focus by default; we just need to set the focus to the required frame (or to the window itself). This is required for Internet Explorer 4. x only. With Internet Explorer 5, we just call frame.print() on a specific frame.

Caution One (Internet Explorer 4.0)

Unfortunately there is no way in Internet Explorer 4.0 to set the focus on to a specific frame because frame.focus() simply has no effect. This is fixed with Internet Explorer 4.01, but users of Internet Explorer 4.0 will be able to print only the frame/window that has a focus.

Caution Two (Internet Explorer 4.01)

If we use frame.focus() followed by idWBPrint.ExecWB, WebBrowser doesn't take the focus change immediately and ends up printing the whole window. We can work around this with a setTimeout() call to retain the idWBPrint.ExecWB command (technically, until the next message loop pump). Try the sample of frame printing we've provided.

Caution Three (Internet Explorer 4.x)

Some unpleasant issues can also arise when we call printFrame from inside a frame. If the user cancels, the printing dialog will "bubble" for each frame nesting level up to the top window. This behavior is undesirable, but help is at hand. If you really need such functionality, you can use the Scripting Factory ActiveX control.

Printing Hidden Content

Another interesting kind of functionality is the printing of hidden HTML documents. For example, an author may want to print an HTML-generated database report. Have a look at the sample and check out the code description if you are interested in the details. The main method, printHidden(url), can be found in the shared include file printHid.js.

<head>
<title>Hidden Document Printing</title>
</head>

<body bgcolor="infobackground">

<p>This is a main page</p>
<script defer language=JScript
src="print.js"></script>
<script defer src="printHid.js"></script>

<p><input disabled name="idPrint" type="button"
  value="Print this page" onclick="print()">
<input disabled name="idPrintFrame" type="button"
  value="Print the frame below"
onclick="printFrame(idFrame)"> </p>
<IFRAME style="visibility: visible" name="idFrame"
  width="50%" height="30%" src="frame.htm">
</IFRAME>

<p><input disabled name="idPrintHidden" type="button"
  value="Print hidden page"
onclick="printURL()"></p>

<script defer>
function window.onload() {
  idPrintHidden.disabled = false;
  idPrint.disabled = false;
  idPrintFrame.disabled = false;
}

function printURL() {
  idPrintHidden.disabled = true;
  // set to handle completition
  window.onprintcomplete = function() {
    idPrintHidden.disabled = false;
  }
  // print the content
  printHidden("report.htm");
}
</script>

</body>
</html>

Print Setup Options

The samples we give above work without any custom controls or extensions. However, there is often a need to adjust page settings, such as headers/footers, portrait/landscape orientation, margins, and so forth -- and we have added the support for this into our free ScriptX ActiveX controlNon-MS link. Feel free to check out ScriptX and a comprehensive printing sample with online page settings customizationNon-MS link.

The Captain Owns Up

Because there is no support for Print Setup customization in the Internet Explorer DOM, many people have asked us "How do you do this Print Setup customization?" Okay, we'll tell you -- and you may laugh at the simplicity of the solution. We invoke a hidden "Page Setup Dialog" and retrieve/change the settings as though we were a user. That's it (although we do this in a smart way to be sure the code is safe). The corresponding dialog control IDs are unchanged among localized Internet Explorer versions, and they are also the same in Internet Explorer 4. x and Internet Explorer 5, so the code works well in all of them. If anything changes in future versions of Internet Explorer, we'll update ScriptX to match it. So far, this is the only way we know of to customize page settings from script.

ScriptXNon-MS link is part of the free MeadCo Scripting Factory -- developed for use with any scripting host: Internet Explorer 4.0 or later HTML, ASP, WSH, or Custom -- which itself forms part of the company's evolving Web applications tool kit. Established in 1988 and based in Cambridge UK, MeadCo builds and maintains online information systems for corporate and institutional clients around the world.



Back to topBack to top

Did you find this material useful? Gripes? Compliments? Suggestions for other articles? Write us!

© 1999 Microsoft Corporation. All rights reserved. Terms of use.