The information in this article applies to:
- Standard and Professional Editions of Microsoft Visual Basic for
Windows, versions 2.0 and 3.0
SUMMARY
From Visual Basic, you can call Windows API routines to change the
default printer settings stored in the Windows WIN.INI file. You can
also broadcast a message to all applications currently loaded in
Windows to try to force them to use this WIN.INI change. However, most
Windows version 3.0 and 3.1 applications are not designed to act on this
broadcast message.
Applications that are started after you change WIN.INI will reflect
your WIN.INI changes, as will applications that are currently loaded, if
the user did not change Printer Setup in the application. But if
the user changed Printer Setup in a currently loaded application, the
application will ignore any changes to WIN.INI during that application's
session.
There are only two ways to ensure that an application will take the changes
made to the printer settings stored in WIN.INI. Either method will work:
- Exit and restart the application, or restart Windows.
- Choose options in the application Printer-Setup dialog box.
This article also describes how to add a Printer Setup dialog to a Visual
Basic application that optionally changes WIN.INI, and it gives example
code showing how to change the default printer in Windows.
MORE INFORMATION
The following steps change the printer settings in the WIN.INI file, and
then broadcast a message to all programs currently loaded in Windows to
make the change take effect:
- Call the Windows API functions GetProfileString and WriteProfileString
to change the printer setting device= in the [windows] section of the
WIN.INI file to one of the printers listed in the [devices] section.
For example, a WIN.INI file would contain the following settings to make
an HP LaserJet the default printer:
[windows]
device=HP LaserJet IIISi PostScript,pscript,LPT1:
[devices]
Generic / Text Only=TTY,FILE:
HP LaserJet IIISi PostScript=pscript,LPT1:
For a detailed article that discusses how to change WIN.INI, search
for the following words in the Microsoft Knowledge Base:
How to Access Windows Initialization Files Within Visual Basic
- Call the Windows API WriteProfileString function using all NULL
pointer parameters to force Windows to reload the WIN.INI file into
memory. (WIN.INI is normally cached in memory and not reloaded until
you restart Windows.) Pass all parameters By Value as type Long with
value 0.
- Call the SendMessage API function with hWnd% parameter set to
HWND_BROADCAST (&hffff) to broadcast a message to all pop-up windows
currently loaded in the system. Setting the wMsg% parameter to
WM_WININICHANGE notifies all top-level windows of a WIN.INI change,
and WM_DEVMODECHANGE notifies them of a device-mode change.
However, if you changed settings in the Printer-Setup dialog box of a
loaded application earlier in this session of Windows, most applications
ignore the SendMessage broadcast. By design, most Windows-based
applications ignore this message, as explained in the Notepad example
given below.
Example of How Notepad Uses WIN.INI Printer Settings
Under Windows, you can change default printer settings in the Printers
section of the Control Panel program. This writes changes to the WIN.INI
file on disk and in memory. Many other applications, such as Microsoft
Word, also write changes to the WIN.INI file.
When Notepad starts, a global variable of type PRINTDLG provides the
structure to initialize the Print dialog box. One of the members of that
structure is hDevNames. It contains three strings that specify the driver
name, printer name, and output port name. When Notepad starts, these three
strings start with a NULL value. This tells Notepad to get its printer
device context (DC) from the WIN.INI file.
If you choose Print Setup from within NotePad and make changes, NotePad
will continue using those changes for the remaining NotePad session, and
the three strings in hDevNames will no longer all be NULL. That session of
NotePad will no longer look in the WIN.INI file, so it will ignore any
WM_WININICHANGE and WM_DEVMODECHANGE messages. Many Windows-based
applications work in this manner. Internally, they process only certain
messages, and they pass all unrecognized messages to the default API
DefWindowProc function, which does nothing.
Because you cannot rely on an application processing WM_WININICHANGE and
WM_DEVMODECHANGE messages, an application such as Visual Basic cannot
force the updated WIN.INI modifications onto another loaded application
by sending Windows messages. To change printer parameters to those changed
in the WIN.INI file, you must use one of these two techniques:
- Exit and restart the application, or restart Windows.
- Use the application's Printer-Setup dialog box to set the parameters.
Adding Printer Setup to a Visual Basic Application
To add a Printer-Setup dialog to a Visual Basic application, use the Common
Dialog printer control provided with the following products:
- Visual Basic version 1.0 Professional Toolkit for Windows
- Professional Edition of Visual Basic version 2.0 for Windows
- Standard or Professional Edition of Visual Basic version 3.0 for Windows
Setting the PrinterDefault property to True writes any Printer Setup
changes
to the WIN.INI file:
CMDialog1.PrinterDefault = True
You can use the Flags property of the Common Dialog printer control to
specify various options, as described on page 208 of "Visual Basic 3.0:
Language Reference." For example, you can have a print dialog with a button
for Printer Setup. Or, you can give the Printer Setup its own dialog box by
setting the Flags property to PD_PRINTSETUP as follows:
CMDialog1.Flags = PD_PRINTSETUP ' PD_PRINTSETUP = &H40&
CMDialog1.Action = 5 ' Displays Printer Dialog for Printer Setup
To change printer settings from a Visual Basic application without user
interaction, call a DLL written in C that calls the Windows API
ExtDeviceMode function. Because Visual Basic does not support function
pointers, you cannot call the ExtDeviceMode function directly from Visual
Basic. A Windows-compatible C compiler is required to create a Windows DLL.
Code Example to Change Windows Default Printer in WIN.INI
The following program demonstrates how to change the default printer in the
WIN.INI file by using Visual Basic code:
- In Visual Basic, place a list box (List1) and a command button
(Command1) on Form1.
- Set the Caption property of Command1 to Set Default Printer.
- Add the following code and three subprograms to the General
Declarations section of Form1:
Option Explicit
' Enter each Declare statement on one, single line:
Declare Function GetProfileString Lib "Kernel"
(ByVal lpAppName As String, ByVal lpKeyName As Any,
ByVal lpDefault As String, ByVal lpReturnedString As String,
ByVal nSize As Integer) As Integer
Declare Function WriteProfileString Lib "Kernel"
(ByVal lpApplicationName As String, ByVal lpKeyName As Any,
ByVal lpString As Any) As Integer
Declare Function SendMessage Lib "User" (ByVal hWnd As Integer,
ByVal wMsg As Integer, ByVal wParam As Integer,
lParam As Any) As Long
Const WM_WININICHANGE = &H1A
Const HWND_BROADCAST = &HFFFF
' Enter the following two lines as one, single line:
Sub GetDriverAndPort (ByVal Buffer As String, DriverName As String,
PrinterPort As String)
Dim r As Integer
Dim iDriver As Integer
Dim iPort As Integer
DriverName = ""
PrinterPort = ""
'The driver name is first in the string terminated by a comma
iDriver = InStr(Buffer, ",")
If iDriver > 0 Then
'Strip out the driver name
DriverName = Left(Buffer, iDriver - 1)
'The port name is the second entry after the driver name
'separated by commas.
iPort = InStr(iDriver + 1, Buffer, ",")
If iPort > 0 Then
'Strip out the port name
PrinterPort = Mid(Buffer, iDriver + 1, iPort - iDriver - 1)
End If
End If
End Sub
Sub ParseList (lstCtl As Control, ByVal Buffer As String)
Dim i As Integer
Do
i = InStr(Buffer, Chr(0))
If i > 0 Then
lstCtl.AddItem Left(Buffer, i - 1)
Buffer = Mid(Buffer, i + 1)
Else
lstCtl.AddItem Buffer
Buffer = ""
End If
Loop While i > 0
End Sub
' Enter the following two lines as one, single line:
Sub SetDefaultPrinter (ByVal PrinterName As String,
ByVal DriverName As String, ByVal PrinterPort As String)
Dim DeviceLine As String
Dim r As Integer
Dim l As Long
DeviceLine = PrinterName & "," & DriverName & "," & PrinterPort
' Store the new printer information in the [WINDOWS] section of
' the WIN.INI file for the DEVICE= item
r = WriteProfileString("windows", "Device", DeviceLine)
' Cause all applications to reload the INI file:
l = SendMessage(HWND_BROADCAST, WM_WININICHANGE, 0, ByVal "windows")
End Sub
- Add the following code to the Command1_Click event procedure:
Dim r As Integer
Dim Buffer As String
Dim DeviceName As String
Dim DriverName As String
Dim PrinterPort As String
Dim PrinterName As String
If List1.ListIndex > -1 Then
'Get the printer information for the currently selected printer
'in the list. The information is taken from the WIN.INI file.
Buffer = Space(1024)
PrinterName = List1.Text
r=GetProfileString("PrinterPorts",PrinterName,"",Buffer,Len(Buffer))
'Parse the driver name and port name out of the buffer
GetDriverAndPort Buffer, DriverName, PrinterPort
If DriverName <> "" And PrinterPort <> "" Then
SetDefaultPrinter List1.Text, DriverName, PrinterPort
End If
End If
- Add the following code to Form_Load event procedure:
Dim r As Integer
Dim Buffer As String
'Get the list of available printers from WIN.INI
Buffer = Space(8192)
r = GetProfileString("PrinterPorts",ByVal 0&,"",Buffer,Len(Buffer))
'Display the list of printer in the list box List1
ParseList List1, Buffer
- Run the program. The list box will display the printer choices from the
WIN.INI file. By clicking the command button, you will set the default
printer in the WIN.INI file.
REFERENCES
"Microsoft Windows Programmer's Reference," Chapters 4 and 6, Microsoft
Press, 1990.
|