Summary

You can retrieve or set the default printer by using different methods, depending on the version of Windows that you use.

More Information

With Windows NT 4.0 (and earlier versions), you cannot use:

Either SetPrinter or SetDefaultPrinter to set the default printer.

Either EnumPrinters or GetDefaultPrinter to get the default printer.

With Windows NT 4.0, you can use:

GetProfileString to get the default printer.

WriteProfileString to set the default printer.

The DEVICE value that you get or set contains three elements that are separated by commas, as follows:

printer name,driver name,port

For example:

My Printer,HPPCL5MS,lpt1:

Note the following:

When you use this method, you must specify a valid printer, driver, and port. If you do not, the APIs will not fail and may cause other programs to set the printer back to the previous valid printer or become confused.

To retrieve the printer name, driver name, and port name of all available printers, use the EnumPrinters API.

Windows NT maps most .ini file references to the registry. As a result, GetProfileString and WriteProfileString still function as if they were running under 16-bit Windows (Microsoft Windows and Windows for Workgroups).

After you set the default printer with either GetPrinter, GetDefaultPrinter, or WriteProfileString, notify all other open programs of the change by broadcasting the WM_SETTINGCHANGE message. Only programs that handle this message recognize the change.

WM_SETTINGCHANGE and WM_WININICHANGE are the same; use WM_SETTINGCHANGE for Win32 programs.

Sample Code

The following sample code shows how to retrieve the default printer (DPGetDefaultPrinter) and set the default printer (DPSetDefaultPrinter).

// You are explicitly linking to GetDefaultPrinter because linking // implicitly on Windows 95/98 or NT4 results in a runtime error.// This block specifies which text version you explicitly link to.#ifdef UNICODE #define GETDEFAULTPRINTER "GetDefaultPrinterW"#else #define GETDEFAULTPRINTER "GetDefaultPrinterA"#endif

// Size of internal buffer used to hold "printername,drivername,portname"// string. You may have to increase this for huge strings.#define MAXBUFFERSIZE 250

// What version of Windows are you running? osv.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&osv);

// If Windows 95 or 98, use EnumPrinters. if (osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) { // The first EnumPrinters() tells you how big our buffer must // be to hold ALL of PRINTER_INFO_2. Note that this will // typically return FALSE. This only means that the buffer (the 4th // parameter) was not filled in. You do not want it filled in here. SetLastError(0); bFlag = EnumPrinters(PRINTER_ENUM_DEFAULT, NULL, 2, NULL, 0, &dwNeeded, &dwReturned); { if ((GetLastError() != ERROR_INSUFFICIENT_BUFFER) || (dwNeeded == 0)) return FALSE; }

// You are explicitly linking to SetDefaultPrinter because implicitly// linking on Windows 95/98 or NT4 results in a runtime error.// This block specifies which text version you explicitly link to.#ifdef UNICODE #define SETDEFAULTPRINTER "SetDefaultPrinterW"#else #define SETDEFAULTPRINTER "SetDefaultPrinterA"#endif

// What version of Windows are you running? osv.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&osv);

if (!pPrinterName) return FALSE;

// If Windows 95 or 98, use SetPrinter. if (osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) { // Open this printer so you can get information about it. bFlag = OpenPrinter(pPrinterName, &hPrinter, NULL); if (!bFlag || !hPrinter) return FALSE;

// The first GetPrinter() tells you how big our buffer must // be to hold ALL of PRINTER_INFO_2. Note that this will // typically return FALSE. This only means that the buffer (the 3rd // parameter) was not filled in. You do not want it filled in here. SetLastError(0); bFlag = GetPrinter(hPrinter, 2, 0, 0, &dwNeeded); if (!bFlag) { if ((GetLastError() != ERROR_INSUFFICIENT_BUFFER) || (dwNeeded == 0)) { ClosePrinter(hPrinter); return FALSE; } }

// The second GetPrinter() will fill in all the current information // so that all you have to do is modify what you are interested in. bFlag = GetPrinter(hPrinter, 2, (LPBYTE)ppi2, dwNeeded, &dwNeeded); if (!bFlag) { ClosePrinter(hPrinter); GlobalFree(ppi2); return FALSE; }

else // NT4.0 or earlier { // Open this printer so you can get information about it. bFlag = OpenPrinter(pPrinterName, &hPrinter, NULL); if (!bFlag || !hPrinter) return FALSE;

// The first GetPrinter() tells you how big our buffer must // be to hold ALL of PRINTER_INFO_2. Note that this will // typically return FALSE. This only means that the buffer (the 3rd // parameter) was not filled in. You do not want it filled in here. SetLastError(0); bFlag = GetPrinter(hPrinter, 2, 0, 0, &dwNeeded); if (!bFlag) { if ((GetLastError() != ERROR_INSUFFICIENT_BUFFER) || (dwNeeded == 0)) { ClosePrinter(hPrinter); return FALSE; } }

If you leave out the SendMessageTimeout call, no other program recognizes the change until you restart the program.

If a different 32-bit program does not handle the WM_SETTINGCHANGE message, the other program do not recognize that the default printer has been changed. You must exit and restart the program to force it to recognize the change.

MAXBUFFERSIZE is too small to hold the following string:

printername,portname,drivername

When you use the WriteProfileString API from this sample code (which you must use only for Windows NT 4.0 and earlier versions), remember that you retrieved the port name that is passed to WriteProfileString by using the 32-bit API GetPrinter.

Although this port name is valid, 16-bit programs cannot read it and may experience problems. If you use this method with Windows NT (4.0 and earlier versions) and 16-bit programs have to understand the new port name, you must use the 16-bit alias for the port name (NE0x, where x is a number). You can find the mapping between 32-bit port names and their 16-bit aliases in the registry.

References

For additional information, click the article numbers below to view the articles in the Microsoft Knowledge Base: