Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Design

Tech Tips


May04: Tech Tips

George is a software engineer in the System Design and Verification group at Cadence Design Systems. He can be reached at [email protected].


Automating Web Page Prints

by Jack Xue

[email protected]

Among the threads I run across on the Internet are: 1. Internet Explorer (IE) users who frequently want to print out specified web pages but don't want to click the OK button on a printing dialog, and 2. web application developers who need to push an HTML file to the client side and print it out without the prompt.

The printing template technique offered by IE 5.5 (and later) may solve some of these problems. Here, I present two more complete alternative solutions that apply to IE 4.0 (and later) running on Windows 98/NT/2000. They work on the client and server side, and also fit for the web service. The first solution is ScriptX, a JavaScript program that uses a free ActiveX control (http://www.meadroid.com/). The second is KiXtart, a standalone application driving another free Windows script (http://www.kixtart.org/).

ScriptX is a nonvisual ActiveX control developed to provide full control over document printing. The basic functionality of ScriptX, which my solution relies on, is freely distributable. Listing One downloads http://www.google.com/ and prints it at the user's default printer without interaction. The ScriptX object is included in the HTML file via the tag <object>. A frameset refers to the web page. Every time the metacommand refresh reloads the frameset, the web page is reloaded through a frame in the frameset. The method onload verifies the existence of the control and sets the header and footer of the print job before calling the method PrintThis, which applies the control's print method. The parameter false for the method print means "do not prompt." The ScriptX package should be downloaded and installed in a directory pointed to by the codebase. Generating this HTML file with a JSP or an ASP, a web application enables its IE users to regularly download and print a desired HTML file. In other words, this automation can be initiated not only from the client but also from the server side. However, when security is important, or if a mismatch exists in user sessions and refreshing time intervals, the clients may be not satisfied with this solution, which motivates us to look for a better method.

If IE users are willing and able to run a standalone application, a more powerful automation can be provided. This solution is based on using RUNDLL32.EXE and MSHTML.DLL (part of the Windows Print API) and also relies on KiXtart, a pure Windows scripting package, which programmatically clicks the OK button in the printing dialog (okay, it's ugly, but bear with me—this is cool). The Java class AutoPrint.java (Listing Two) provides the refreshing time interval to download the web page and save it in a local directory, to start a Windows batch file to run RUNDLL32.EXE with MSHTML.DLL, and finally to run KiXtart to close the prompt. This batch file (Listing Three) is a boiled-down version of PrintPDF.bat written by Rob van der Woude (http://www.robvanderwoude.com/). The solution lets you use any networked printer. The path to MSHTML.DLL may be different on a different machine. The printer path can be found in the Registry. The directory where KiXtart is installed should be a part of the PATH. The user authentication can be implemented as a part of the URL connection process. Moreover, this solution provides a framework to host the web service client-side code, which carries out the object internalization and externalization and the implementation of SSL. Thanks to Jerry Mead of Mead Inc. and Rob van der Woude for their valuable help.

Building a Static Library For Device Drivers

by Alan MacInnes

[email protected]

This tip might seem straightforward to users of Visual Studio or other GUI-enhanced, one-stop-shopping centers that most Windows-based development environments have become today. However, the Windows Driver Development Kit (DDK) is still rather neolithic, and the most commonly used model is to start with a standard example and modify it. To that end, I present a static library of routines used by device drivers that can be easily built under the DDK. This fills a hole in the DDK documentation, as far as I can tell, and should be helpful to some readers. The static library, which is a .lib file (of course), can then be included in any build for a device driver that calls one or more routines in the static library.

An example SOURCES file for building a static library is as follows:

!IF 0

This is the "SOURCES" file for building the

static library.

!ENDIF

TARGETNAME=StaticLibraryTemplate

TARGETTYPE=DRIVER_LIBRARY

TARGETPATH=$(DDK_LIB_DEST)

SOURCES=StaticLibraryRoutineOne.c

StaticLibraryRoutineTwo.c

The generated .lib file is placed in the folder specified by the environment variable DDK_LIB_DEST. This environment variable is automatically defined for you by the DDK build environment. In the SOURCES file used for building a device driver, the following line would be included to refer to this static library:

TARGETLIBS=

$(DDK_LIB_PATH)\StaticLibraryTemplate.lib

The environment variable DDK_LIB_PATH refers to the same folder as DDK_LIB_DEST. Listing Four is the source code for the trivial sample routines in the static library—StaticLibraryRoutineOne.c, StaticLibraryRoutineTwo.c, and StaticLibraryTemplate.h.

DDJ

Listing One

<html>
<head>
<meta http-equiv="Refresh" content="60">
<!-- MeadCo ScriptX -->
<object id="factory" viewastext  style="display:none"
  classid="clsid:1663ed61-23eb-11d2-b92f-008048fdd814"
  codebase="c:\scriptx\ScriptX.cab#Version=6,1,430,5">
</object>
<script defer>
function onload(){
  if (!factory.object){
    alert("Onload cannot find ScriptX Control.");
    return;
  }
  factory.printing.header = "Test Header";
  factory.printing.footer = "Test Footer";
  PrintThis();
}
function PrintThis(){
  if (!factory.object){
    alert("PrintThis cannot find ScriptX Control.");
    return;
  }
  factory.printing.print(false);
}
</script>
</head>
<frameset name="frameset" rows="*" onload="onload()">
  <frame name="frame_for_web_site" src="http://www.google.com">
</frameset>
</html>

Back to Article

Listing Two

import java.io.*;
import java.net.*;
import java.util.*;

public class AutoPrint{
  public static void main(String arg[]){
    // params for calling printHtml.bat
    String args[] = new String[3];
    args[0] = new String("c:\\autoprint\\printHtml.bat");
    args[1] = new String("c:\\autoprint\\testpage.html");
    args[2] = new String("\\\\printer_server\\a_printer");
    String testSite = "http://www.google.com";
    // the main loop
    while (true) {
      // retrieve the web page
      StringBuffer sb = new StringBuffer(100000);
      try {
        URL url = new URL(testSite);
    InputStream in = url.openStream();
    in = new BufferedInputStream(in);
    Reader reader = new InputStreamReader(in);
    int c;
    while ((c = reader.read()) != -1){
      sb.append((char)c);
    }
    in.close();
      } catch (MalformedURLException e) {
    System.err.println("Malformed: " + e);
      } catch (IOException e) {
    System.err.println("I/O Exception: " + e);
      }
      // save to a file
      File file = new File(args[1]);
      try{
    FileWriter fw = new FileWriter(file);
    fw.write(sb.toString());
    fw.close();
      } catch (Exception e){
    System.out.println(e.toString());
      }
      // is the file readable?
      if (!file.canRead()){
    System.out.println("Cannot read the file.");
    return;
      }
      // call printHtml.bat
      Process p = null;
      try {
    p = Runtime.getRuntime().exec(args);
      } catch (Exception e) {
    System.out.println(e.toString());
      }
      // wait for printHtml.bat to finish
      try {
    p.waitFor();
      } catch (InterruptedException e) {
        // need to do nothing.
      }
      // make a log
      Date date = new Date();
      System.out.println(date.toString() + " printHtml.bat called.");
      // be ready for next iteration
      try {
    Thread.sleep(600000);
    if(!file.delete()) {
      System.out.println("Cannot delete the file.");
      return;
    }
      } catch (Exception e) {
    System.out.println(e.toString());
      }
    }
  }
}

Back to Article

Listing Three

@ECHO OFF
SETLOCAL
SET File="%1"
SET Printer="%2"
IF NOT DEFINED File GOTO End
IF NOT DEFINED Printer GOTO End
:: Create a temporary Kix file to "press" Print button>
 %TEMP%.\%~n0.kix ECHO.; Wait a few seconds for the Print dialog to appear>
>%TEMP%.\%~n0.kix ECHO SLEEP 2>
>%TEMP%.\%~n0.kix ECHO.; Press "Print" (Enter) using SendKeys function>
>%TEMP%.\%~n0.kix ECHO IF SETFOCUS("Print") = 0>
>%TEMP%.\%~n0.kix ECHO   $RC = SENDKEYS("{ENTER}")>
>%TEMP%.\%~n0.kix ECHO ENDIF

:: Actual print command
START RUNDLL32.EXE c:\winnt\system32\MSHTML.DLL,PrintHTML %File% 
%Printer%
:: Call the temporary Kix file to "press" Print button, then delete it
START /WAIT KIX32.EXE %TEMP%.\%~n0.kix
DEL %TEMP%.\%~n0.kix
:End
ENDLOCAL

Back to Article

Listing Four

/* StaticLibraryRoutineOne.c */
#include <ntddk.h>
#include "StaticLibraryTemplate.h"

VOID
FirstRoutine()
{
    DbgPrint("First routine entered in Static Library\n");
}
/* StaticLibraryRoutineTwo.c */
#include <ntddk.h>
#include "StaticLibraryTemplate.h"

VOID
SecondRoutine()
{
    DbgPrint("Second routine entered in Static Library\n");
}
/* StaticLibraryTemplate.h */
// Function prototypes for the two routines in the static library.

VOID FirstRoutine();
VOID SecondRoutine();

Back to Article


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.