SetWebBrowser allows your application to pass in a pointer to the WebBrowser instance. Call SetWebBrowser, specifying NULL to release the reference.
ReadDlgSettings reads the settings in the Page Setup and Print dialog boxes into the data members.
Print writes the settings from the data members back into the Page Setup and Print dialog boxes and starts the printing process.
GetPrinterCount returns the number of printers that are defined on the system. This is valid after calling ReadDlgSettings.
GetDefaultPrinterName returns the name of the default printer, or an empty string if there is no default printer. You should verify that a default printer is available before calling ReadDlgSettings or Print as they will not function properly unless there is at least one printer defined.
GetPrinterName returns the name of a specified printer. Specify an integer from 0 to 1 minus the number returned by GetPrinterCount.
The data members are self-explanatory. They are valid after calling ReadDlgSettings. You can modify any of these values to set custom print settings and then call Print to print with your specified settings.
The CWebBrowserPrint class installs a system hook with thread scope. The hook is only active from the ReadDlgSettings and Print functions. ReadDlgSettings installs the hook, calls ExecWB to invoke the Page Setup and Print dialog boxes, reads the dialog box settings into the class data members, clicks Cancel to dismiss the dialog boxes, and then removes the hook. Print installs the hook, calls ExecWB to invoke the Page Setup and Print dialog boxes, and transfers the changes from the class data members back to the dialog box. Print then prints the Web page, clicks OK to dismiss the dialog boxes, and then removes the hook.
Here is some sample code to illustrate how to use the class in an application. Note that we are checking to make sure there is a default printer before calling ReadDlgSettings or Print.
The phookctl sample exposes the printer settings from an ActiveX control. This gives you the ability to set custom print settings from script in a Web page as shown below.
<HTML>
<HEAD>
<OBJECT ID="wbp"
CLASSID="CLSID:778C58A9-81B6-11D3-BB8F-00C04FA3471C">
</OBJECT>
<SCRIPT LANGUAGE="VBScript">
Sub Print()
If Len(wbp.DefaultPrinterName) = 0 Then
MsgBox "No default printer!"
Exit Sub
End If
wbp.Header = "My Header"
wbp.Orientation = 2 ' Landscape
wbp.Print
End Sub
</SCRIPT>
</HEAD>
<BODY>
<INPUT TYPE="BUTTON" VALUE="Print" ONCLICK="Print()">
</BODY>
</HTML>
Note that there is no need to call SetWebBrowser or ReadDlgSettings when using this control on a Web page, because the control can obtain this information on its own. However, SetWebBrowser is exposed so you can set the reference when hosting the WebBrowser control in your own application.
Lastly, the phookvb sample demonstrates using phookctl in a VB application that hosts the WebBrowser control.
Hooking the Page Setup and Print Dialog Boxes
Install a system hook and take full control over the Page Setup and Print dialog boxes.
Advantages Disadvantages
Complete control over all Page Setup and Print dialog box functions. Uses undocumented aspects of the WebBrowser's implementation and is therefore unsupported.
This method uses an old trick called the "CBT" hook, which stands for computer-based training. Windows provides a way to install a system hook that allows an application to receive notifications of certain windows events before the windows themselves are notified. This facility was originally intended to only support online help applications so that they could do things like pop up a help window whenever a certain dialog box is opened by the user. Using this facility to manipulate other applications against their will is usually frowned upon and is not considered to be good practice.
Even though this technique employs very questionable methods, it is probably the smoothest solution of all. You can control any of the settings that are exposed in the user interface of the product.
The following Win32 functions are used to create a system hook. SetWindowsHookEx installs the hook. CallNextHookEx chains a hook procedure to the next hook procedure. UnhookWindowsHookEx removes the hook. Refer to the Win32 documentation for detailed information on these functions. You will also need to implement a hook procedure so that Windows knows where to send the notifications. A skeletal version of a hook procedure is shown below.
The documentation for SetWindowsHookEx covers the various notifications that can be received in your hook procedure. For our purposes, we are interested in two notifications-HCBT_CREATEWIN and HCBT_ACTIVATE.
HCBT_CREATEWIN notifies us when a window is about to be created, before it receives its WM_CREATE message. The wParam parameter identifies the HWND of the window and lParam gives us access to the CREATESTRUCT for the window. From the CREATESTRUCT, we can use lpszClass to determine what type of window is being created. We can also alter the position of the window to move it off screen so that the user will not see the dialog.
HCBT_ACTIVATE notifies us when a window is about to receive the WM_ACTIVATE message. It is at this point that we can take control of the dialog. The idea is to send messages to the window to make it think that the user is interacting with the dialog. You can enter text into textboxes, set checkboxes and radio buttons, and click OK or Cancel. The easiest way to identify controls in the dialog is to find out their resource ID's with a tool like Spy++. Then you can call GetDlgItem to obtain the HWND of the control and SendMessage to interact with it.
The following samples are provided to demonstrate how to automatically control the WebBrowser's Page Setup and Print dialog boxes in a number of scenarios. Please note that these samples will not work with Windows 2000 due to changes in the architecture of the Print dialog box.
Sample code Function of this code
Phookmfc (wb_print02.exe) Demonstrates printing with custom print settings from an MFC application.
Phookctl (wb_print03.exe) Demonstrates printing with custom print settings from script on a Web page.
Phookvb (wb_print04.exe) Uses phookctl to print with custom print settings from a VB application.
The code that does all of the dirty work in the samples is implemented in a reusable class named CWebBrowserPrint. This is defined in the WebBrowserPrint.h and WebBrowserPrint.cpp files. This makes it easy to incorporate the ability to set custom print settings in any C++ application that is hosting the WebBrowser control. The public aspects of the class are shown below.
How can I specify the target printer or set Landscape mode and other print attributes? The WebBrowser does not expose a way to programmatically specify a target printer or any other print attributes; therefore, there is no directly-supported way of programmatically defining these settings from script or from an application hosting the WebBrowser control.
There are two workarounds. The first and most straightforward approach is to hook the Print dialog box and send a message to appropriate window control (that is, send a WM_SETTEXT message to the Printer combo box to select the desired printer). The other approach is to temporarily change the application default printer. Both of these approaches are discussed further in the Printing Workarounds section.