October 30, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Function to Set Default Printer

  • July 19, 2000
  • By Ivan Cerrato
  • Send Email »
  • More Articles »

Environment: Windows NT4 SP3; Developed with Visual C++ 6 SP3

SetPrinter is a simple DLL COM that enables you to programmatically set the default printer:
  • The problem that I faced is that if you attempt to specify the default printer from an application, that printer is not actually realized as the default printer by Windows immediately.

You can resolve this problem by doing the following:

  • First, install the driver printer on your machine;
  • If you work on Windows 2000, you must use 'SetDefaultPrinter' followed by the printer's name.
  • If you work on Windows 98 or Windows NT 4 you must first call the OpenPrinter function in order to retrieve the printer handle. Then you need to call the GetPrinter function twice in order to obtain the printer informations. You then need to call the WriteProfileString function (Windows NT)
  • Finally, you must notify all windows of this new Windows setting as follows:
lResult = SendMessageTimeout(HWND_BROADCAST, 
                             WM_SETTINGCHANGE, 
                             0L, 0L,
                             SMTO_NORMAL, 
                             1000, 
                             NULL);

Or instead of going through all of that, you can use my COM component and its DPSetDefaultPrinter method. Here is the code for that method so that you can see all that needs to take place to perform a seemingly very simple task.

STDMETHODIMP CCustomPrinter::DPSetDefaultPrinter(BSTR pPrinterName, 
int *Result)
{
USES_CONVERSION;

  BOOL bFlag;
  OSVERSIONINFO osv;
  DWORD dwNeeded = 0;
  HANDLE hPrinter = NULL;
  PRINTER_INFO_2 *ppi2 = NULL;
  LPTSTR pBuffer = NULL;
  LONG lResult;
  
  // What version of Windows are you running?
  osv.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  GetVersionEx(&osv);
  
  if (!pPrinterName)
	*Result = 0;
	return S_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((char*)OLE2CA(pPrinterName), &hPrinter, NULL);
    if (!bFlag || !hPrinter)
		*Result = 0;
		return S_FALSE;    
    // The first GetPrinter() tells you how big our buffer should
    // be in order to hold ALL of PRINTER_INFO_2. Note that this will
    // usually return FALSE. This only means that the buffer (the 3rd
    // parameter) was not filled in. You don't want it filled in 
here...
    GetPrinter(hPrinter, 2, 0, 0, &dwNeeded);
    if (dwNeeded == 0)
    {
      ClosePrinter(hPrinter);
      *Result = 0;
	  return S_FALSE;
    }
    
    // Allocate enough space for PRINTER_INFO_2...
    ppi2 = (PRINTER_INFO_2 *)GlobalAlloc(GPTR, dwNeeded);
    if (!ppi2)
    {
      ClosePrinter(hPrinter);
      *Result = 0;
	  return S_FALSE;
    }
    
    // The second GetPrinter() will fill in all the current 
information
    // so that all you need to do is modify what you're interested 
in...
    bFlag = GetPrinter(hPrinter, 2, (LPBYTE)ppi2, dwNeeded, 
&dwNeeded);
    if (!bFlag)
    {
      ClosePrinter(hPrinter);
      GlobalFree(ppi2);
      *Result = 0;
	  return S_FALSE;
    }
    
    // Set default printer attribute for this printer...
    ppi2->Attributes |= PRINTER_ATTRIBUTE_DEFAULT;
    bFlag = SetPrinter(hPrinter, 2, (LPBYTE)ppi2, 0);
    if (!bFlag)
    {
      ClosePrinter(hPrinter);
      GlobalFree(ppi2);
      *Result = 0;
	  return S_FALSE;
    }
    
    // Tell all open applications that this change occurred. 
    // Allow each application 1 second to handle this message.
    lResult = SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0L,
      (LPARAM)(LPCTSTR)"windows", SMTO_NORMAL, 1000, NULL);
  }
  
  // If Windows NT, use the SetDefaultPrinter API for Windows 2000,
  // or WriteProfileString for version 4.0 and earlier...
  else if (osv.dwPlatformId == VER_PLATFORM_WIN32_NT)
  {
#if(WINVER >= 0x0500)
    if (osv.dwMajorVersion >= 5) // Windows 2000 or later...
    {
      bFlag = SetDefaultPrinter(pPrinterName);
      if (!bFlag)
        *Result = 0;
		return S_FALSE;
    }
    
    else // NT4.0 or earlier...
#endif
    {
      // Open this printer so you can get information about it...
      bFlag = OpenPrinter((char*)OLE2CA(pPrinterName), &hPrinter, 
NULL);
      if (!bFlag || !hPrinter)
        *Result = 0;
		return S_FALSE;
      
      // The first GetPrinter() tells you how big our buffer should
      // be in order to hold ALL of PRINTER_INFO_2. Note that this 
will
      // usually return FALSE. This only means that the buffer (the 
3rd
      // parameter) was not filled in. You don't want it filled in 
here...
      GetPrinter(hPrinter, 2, 0, 0, &dwNeeded);
      if (dwNeeded == 0)
      {
        ClosePrinter(hPrinter);
        *Result = 0;
		return S_FALSE;
      }
      
      // Allocate enough space for PRINTER_INFO_2...
      ppi2 = (PRINTER_INFO_2 *)GlobalAlloc(GPTR, dwNeeded);
      if (!ppi2)
      {
        ClosePrinter(hPrinter);
        *Result = 0;
		return S_FALSE;
      }
      
      // The second GetPrinter() fills in all the current
      // information...
      bFlag = GetPrinter(hPrinter, 2, (LPBYTE)ppi2, dwNeeded, 
&dwNeeded);
      if ((!bFlag) || (!ppi2->pDriverName) || (!ppi2->pPortName))
      {
        ClosePrinter(hPrinter);
        GlobalFree(ppi2);
        *Result = 0;
		return S_FALSE;
      }
      
      // Allocate buffer big enough for concatenated string.
      // String will be in form "printername,drivername,portname"...
      pBuffer = (LPTSTR)GlobalAlloc(GPTR,
        lstrlen((char*)OLE2CA(pPrinterName)) +
        lstrlen(ppi2->pDriverName) +
        lstrlen(ppi2->pPortName) + 3);
      if (!pBuffer)
      {
        ClosePrinter(hPrinter);
        GlobalFree(ppi2);
		*Result = 0;
		return S_FALSE;
      }
      
      // Build string in form "printername,drivername,portname"...
      lstrcpy(pBuffer, (char*)OLE2CA(pPrinterName));  lstrcat
(pBuffer, ",");
      lstrcat(pBuffer, ppi2->pDriverName);  lstrcat(pBuffer, ",");
      lstrcat(pBuffer, ppi2->pPortName);
      
      // Set the default printer in Win.ini and registry...
      bFlag = WriteProfileString("windows", "device", pBuffer);
      if (!bFlag)
      {
        ClosePrinter(hPrinter);
        GlobalFree(ppi2);
        GlobalFree(pBuffer);
        *Result = 0;
		return S_FALSE;
      }
    }
    
    // Tell all open applications that this change occurred. 
    // Allow each app 1 second to handle this message.
    lResult = SendMessageTimeout(HWND_BROADCAST, 
				 WM_SETTINGCHANGE, 
				 0L, 0L,
				 SMTO_NORMAL, 
				 1000, 
				 NULL);
  }
  
  // Cleanup...
  if (hPrinter)
    ClosePrinter(hPrinter);
  if (ppi2)
    GlobalFree(ppi2);
  if (pBuffer)
    GlobalFree(pBuffer);
  
*Result = 1;
return S_OK;

}

Installation

  • On each machine where you want to use the SetPrinter component, you must register the DLL as follows:
    regsvr32 <path>SetPrinter.dll;

Downloads

Download SetPrinter project code - 40 Kb






Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel