Login
Skip Navigation Links
Home
Tools & Services
Resources
Web & App DevelopmentExpand Web & App Development
Software / UtilitiesExpand Software / Utilities
Customer Support
E-mail Client Setup





Using Internet Explorer Print Templates

This section describes how you can customize the way in which the WebBrowser Control and Microsoft Internet Explorer print and preview documents, using print templates. In addition, it includes information which Microsoft left out of their MSDN documentation for Print Template functionality, but I found to be nessesary to achieve any results.

Microsoft has a lot of information and some examples on using Print Templates in their articles (Beyond Print Preview: Print Customization for Internet Explorer 5.5 * ) and detailed documentation (Print Templates * ).

* Some of the materials below were copied from the websites referenced in the prior links.

What are Print Templates and What Can I Do with Custom Print Templates?

Print templates are HTML documents with JavaScript that control how the Internet Explorer prints displayed pages and how it behaves doing so.
In addition, you can find a few examples of the functionality in the sample application provided on MSDN website - Beyond Print Preview: Print Customization for Internet Explorer 5.5

The new print customization possibilities add a new layer of possibilities to Internet Explorer as a platform for application development. By creating a print template, you can control:
  • The layout of pages when printed/previewed, and the content that is printed/previewed on them.
  • How print jobs are handled—for instance, which pages are printed in what order.
  • Programmatically control printing functionality and print options (number of copies, page margins, page orientation).
  • Control whether Print Prompt dialog is displayed or not.
  • The look of the Print Preview window and controls available on the print preview user interface.
Because you now have extensive layout and handling control over printing, Internet Explorer can fit many new application scenarios, such as:
  • Adding boilerplate text to print jobs, including company logos, legal notices, and advertisements.
  • Customized placement and styling for header and footer elements, such as page numbers or chapter headings.
  • Customized printing for scheduling or appointment applications, which gives the user different layout or binding options.
  • Multi-fold brochure printing.
  • Book-style printing using mirrored margins for the odd and even pages.
  • Producing consistent printouts for reports, letters, preprinted forms, etc.

How Does It Work?

To pass a print template to the WebBrowser control, you must be able to issue or intercept the IDM_PRINT and IDM_PRINTPREVIEW commands through IOleCommandTarget::Exec. The print template path is passed to the WebBrowser control in the pVarArgIn VARIANT argument to IOleCommandTarget::Exec.

What Do I Need To Make It Work?

  • Webpage or Website that you want to print.
  • Custom browser that hosts Internet Explorer control or ActiveX control embeded within the desired page.
  • Note: this functionalty will work only if the browser is embedded within a Desktop Forms Application or the page has ActiveX control embedded to invoke printing.
  • Print Temlate that describes how the page should be printed.

Step-By-Step Implementation

Step 1: Create Your Webpage or Website

I would assume that this is already done and you don't need any instructions on this part.

Step 2: Create Host Application that has WebBrowser embedded or write an ActiveX Control

Embedded Browser. This example uses managed Web Browser control. I was able to achieve the desired results using Microsoft Visual Studio 2005 (C#).

  • Create "Forms" application and drop WebBrowser control on to the form (name it "wb").
  • Add reference to SHDocVw.dll (located in your System32 folder).
  • Paste code below and invoke it when needed.
  • You will need existing template to test this (and save it under C:\PrintTemplate.html). You can find one in Step 3.
private void Print()
{
object objIn = @"c:\PrintTemplate.html";
object objOut = null;

// Get ActiveX Instance of the WebBrowser control
IWebBrowser2 iWB = (IWebBrowser2)wb.ActiveXInstance;

// Invoke ExecWB function of the ActiveX Instance, passing in the template path
iWB.ExecWB(OLECMDID.OLECMDID_PRINTPREVIEW, OLECMDEXECOPT.OLECMDEXECOPT_DODEFAULT, ref objIn, ref objOut);
}


ActiveX Control. This example uses unmanaged C++ code to invoke host browser's IOleCommandTarget::Exec function.

This example works for both, Normal Internet Explorer and Modal IE windows. When I was researching, I realized that there was a number of people having problems executing Print from modal windows.

  • Start new "MFC ActiveX Control" project.
  • Add new public method called Print(LPCTSTR templatePath, BOOL vPreview, BOOL vShowPrompt).
  • Paste code below into the body of the Print method.
  • Add the code for the <object> to the webpage.
  • Create the template file in the same directory as the target page (You can find one in Step 3).
  • Invoke object's Print method from JavaScript on the page, passing in the proper parameters.

Implementation for the Print method

void CaxIEPrintCtrl::Print(LPCTSTR templatePath, BOOL vPreview, BOOL vShowPrompt)
{
    CComPtr<IHTMLDocument2> pDoc;
    HRESULT hRes = S_OK;
    // **************************************************************************
    // There are two ways to get to OleCommandTarget,
    // one for Normal Window, other is for Modal window.
    // OleCommandTarget is needed to execute "exec" method on it for
    // print & print preview (passing in the path for the template)
    // Normal Flow:
    // ClientSite->ServiceProvider->TopLevelBrowser->WebBrowser2->Dispatch->HTMLDocument2->OleCommandTarget
    // Modal Window Flow:
    // ClientSite->ServiceProvider->               HTMLWindow2            ->HTMLDocument2->OleCommandTarget
    // **************************************************************************
    // Getting client site of the control (should be embedded using "<object>" tag
    LPOLECLIENTSITE pClientSite = GetClientSite();
    // Service Provider
    CComPtr<IServiceProvider> pSP;
    pClientSite->QueryInterface(IID_IServiceProvider, (void**)&pSP);
    // Get TopLevelBrowser
    // if returns S_OK - Running in normal window;
    // else - modal window or error encountered.
    CComPtr<IServiceProvider> pSP2;
    hRes = pSP->QueryService(SID_STopLevelBrowser, IID_IServiceProvider, reinterpret_cast<void **>(&pSP2));
    if (SUCCEEDED(hRes)) {  // Running in non-modal window.
            // Get WebBrowser2
            CComPtr<IWebBrowser2> pWB;
            hRes = pSP2->QueryService(SID_SWebBrowserApp, IID_IWebBrowser2, (void**)&pWB);
            if (FAILED(hRes))       {       return; }
            // Get Dispatch from Web Browser
            CComPtr<IDispatch> pDisp;
            hRes = pWB->get_Document(&pDisp);
            // Get IHTMLDocument2 for the dispatch
            pDisp->QueryInterface(IID_IHTMLDocument2, (void**)&pDoc);
    }

    else { // Running in Modal Window
            // Get HTML window, containing HTMLDocument2
            CComPtr<IHTMLWindow2> pHW(NULL);
            hRes = pSP->QueryService(SID_SHTMLWindow, IID_IHTMLWindow2, (void**)&pHW);
            if (SUCCEEDED(hRes)){
                    // Get document from HTMLWindow2
                    pHW->get_document(&pDoc);
            }
            else    {       return; }
    }
    // Get document's URL
    BSTR cURL;
    pDoc->get_URL(&cURL);
    CString sUrl(cURL);
    SysFreeString(cURL);
    // Add template path to the host document's folder
    int lPos = sUrl.ReverseFind('/');
    sUrl = sUrl.Left(lPos + 1);
    sUrl += templatePath;
    // Convert final template path to BSTR
    VARIANT vTemplatePath;
    V_VT(&vTemplatePath) = VT_BSTR;
    V_BSTR(&vTemplatePath) = sUrl.AllocSysString();


    // Get OleCommandTarget for HTMLDocument2
    CComPtr<IOleCommandTarget> pCT;
    pDoc->QueryInterface(IID_IOleCommandTarget, (void**)&pCT);
    if (vPreview)           // PRINT PREVIEW
    {       pCT->Exec(&CGID_MSHTML, IDM_PRINTPREVIEW, OLECMDEXECOPT_DODEFAULT, &vTemplatePath, NULL);       }
    else
    {       if (vShowPrompt)        // PRINT (With PROMPT)
            {       pCT->Exec(&CGID_MSHTML, IDM_PRINT, OLECMDEXECOPT_PROMPTUSER, &vTemplatePath, NULL);     }
            else                    // PRINT (W/o PROMPT)
            {       pCT->Exec(&CGID_MSHTML, IDM_PRINT, OLECMDEXECOPT_DONTPROMPTUSER, &vTemplatePath, NULL); }
    }
}

Code to embed object into the web page

<object id="iePrint" name="iePrint" classid="clsid:[Class ID Goes Here]" codebase="iePrint.cab"></object>

Code to invoke print method from the web page

// To Print With Prompt
javascript:iePrint('PrintTemplate.html', false, true);
// To Print Without Prompt
javascript:iePrint('PrintTemplate.html', false, false);
// To show print preview
javascript:iePrint('PrintTemplate.html', true, true);

Step 3: Create Print Tempate

There are plenty of resources that duplicate MSDN code and examples for Print Templates. I suggest going to the MSDN website and downloading "Print and Preview Template Test App" that comes with 8 examples of templates (Download Here).
This application also lets you test your own templates.

Template2.htm: Minimal Template Supporting Printing

<!-- Template2.htm: Minimal Template Supporting Printing
This template demonstrates a minimal print template with enough support to
enable printing as well as previewing. It is the same as tmplt1.htm with the
addition of the TEMPLATEPRINTER element and scripts to provide printing support.

The scripts begin with the function CheckPrint. This function is the
onlayoutcomplete event handler for the second LAYOUTRECT element, wrapped in
a 100 millisecond timeout. CheckPrint checks the dialogArguments.__IE_PrintType
property to determine whether to preview the document, print the document first
prompting the user with the Print Dialog box, or print without prompting the
user at all. The timeout is important because the device context (DC) cannot
render to the printer or screen until the onlayoutcomplete event has finished.
The timeout delays printing until after the onlayoutcomplete event has been
consumed. A timeout of as little as one millisecond can be enough allow the
onlayoutcomplete event to finish. To be on the safe side, the timer is set for
100 milliseconds in this example.

PrintPrep is an important function because it sets an onreadystatechange handler
to make sure the template's source document has been completely loaded into the
template before printing. -->

<HTML XMLNS:IE>
<HEAD>
<?IMPORT NAMESPACE="IE" IMPLEMENTATION="#default">
<STYLE TYPE="text/css">
.lorstyle
{
width:5.5in;
height:8in;
margin:1in;
background:white;
border:1 dashed gray;
}
.pagestyle
{
width:8.5in;
height:11in;
background:#FFFF99;
border-left:1 solid black;
border-top:1 solid black;
border-right:4 solid black;
border-bottom:4 solid black;
margin:10px;
}
</STYLE>

<SCRIPT LANGUAGE="JScript">
function CheckPrint()
{
switch (dialogArguments.__IE_PrintType)
{
case "Prompt":
if (printer.showPrintDialog())
PrintPrep();
break;
case "NoPrompt":
PrintPrep();
break;
case "Preview":
default:
break;
}
}

function PrintPrep()
{
if (layoutrect1.contentDocument.readyState == "complete")
{
// This block will be called when printing with user prompt
// because the Print dialog box gives time for the content
// document to complete loading
PrintNow();
}
else
{
// This block will usually be called when printing w/o user prompt
// and sets an event handler that listens for the loading of the content
// document before printing. Sometimes, however, the content document
// will be loaded in time for the previous block to execute
layoutrect1.contentDocument.onreadystatechange = PrintWhenContentDocComplete;
}
}

function PrintWhenContentDocComplete()
{
if (layoutrect1.contentDocument.readyState == "complete")
{
layoutrect1.contentDocument.onreadystatechange = null;
PrintNow();
}
}

function PrintNow()
{
printer.startDoc("Printing from Tmplt2.htm");
printer.printPage(page1);
printer.printPage(page2);
printer.stopDoc();
}
</SCRIPT>
<IE:TEMPLATEPRINTER ID="printer"/>
</HEAD>

<BODY>

<IE:DEVICERECT ID="page1" CLASS="pagestyle" MEDIA="print">
<IE:LAYOUTRECT ID="layoutrect1" CONTENTSRC="document" CLASS="lorstyle" NEXTRECT="layoutrect2"/>
</IE:DEVICERECT>

<IE:DEVICERECT ID="page2" CLASS="pagestyle" MEDIA="print">
<IE:LAYOUTRECT ID="layoutrect2" CLASS="lorstyle" ONLAYOUTCOMPLETE="setTimeout('CheckPrint()', 100)"/>
</IE:DEVICERECT>

</BODY>
</HTML>


Suggest your links and resources for this directory
Site Map Copyright © 2001-2008 Web Appearance