Поделиться через


Установка обработчика печати

Чтобы установить обработчик печати, приложение установки должно вызвать функцию AddPrintProcessor очереди очереди. Чтобы связать обработчик печати с очередью печати, укажите его имя в INF-файле в записи PrintProcessor. Эта запись должна быть включена для каждой очереди печати, с которой должен быть связан обработчик печати. Дополнительные сведения см. в разделе Inf-файлы принтера.

Когда приложение установки вызывает функцию AddPrinter очереди очереди, используя в качестве входного аргумента структуру {PRINTER_INFO_2](/windows/win32/printdocs/printer-info-2), оно указывает имя процессора печати (полученное из INF-файла) в качестве элемента структуры.

Связывание обработчика печати с очередью печати, установленной на pnp

Если диспетчер Plug and Play (PnP) обнаруживает и устанавливает очередь печати в системе под управлением Windows 2000 или Windows XP, а INF-файл, используемый для установки очереди печати, содержит запись PrintProcessor, отличающуюся от стандартного обработчика печати Windows , winPrint, обработчик печати не будет связан с очередью печати. Однако будет установлен обработчик печати.

Обратите внимание, что при установке очереди печати с помощью мастера добавления принтера обработчик печати будет правильно связан с очередью печати.

Обратите внимание также, что диспетчер PnP в Microsoft Windows Server 2003 и более поздних версиях правильно связывает обработчик печати с очередью печати.

Чтобы связать обработчик печати с очередью печати для Plug and Play установок в Windows 2000 и Windows XP, включите PRINTER_EVENT_INITIALIZE регистр в функцию DrvPrinterEvent библиотеки DLL интерфейса принтера. Для Microsoft Windows Server 2003 и более поздних версий не требуется добавлять PRINTER_EVENT_INITIALIZE регистр в функцию DrvPrinterEvent .

В следующем примере кода для элемента pPrintProcessorструктуры PRINTER_INFO_2 задается имя обработчика печати, а затем вызывается функция SetPrinter для обновления параметров принтера. Обратите внимание, что имя обработчика печати в gszPrintProc должно совпадать с именем в записи PrintProcessor в INF-файле.

BOOL
DrvPrinterEvent(
               LPWSTR  pPrinterName,
               INT     Event,
               DWORD   Flags,
               LPARAM  lParam
               )

{
  PRINTER_DEFAULTS  PrinterDef = {NULL, NULL, PRINTER_ALL_ACCESS};
  HANDLE            hPrinter;
  LPPRINTER_INFO_2  pInfo = NULL;
  DWORD             cbNeeded;
  TCHAR             gszPrintProc[] = TEXT("<Print processor name>");
  BOOL              bRet = TRUE;

  switch (Event)
  {
    case PRINTER_EVENT_INITIALIZE:
      if (OpenPrinter(pPrinterName, &hPrinter, &PrinterDef))
      {
        if ( !GetPrinter( hPrinter, 2, (LPBYTE) pInfo, 0, &cbNeeded ) &&
           (GetLastError() != ERROR_INSUFFICIENT_BUFFER) )
        {
          bRet = FALSE;
        }
        if (bRet == TRUE)
        {
          pInfo = (LPPRINTER_INFO_2) LocalAlloc(LPTR, cbNeeded);
          bRet = pInfo ? TRUE : FALSE;
        }
        if (bRet == TRUE)
        {
          if (GetPrinter(hPrinter, 2, (LPBYTE) pInfo, cbNeeded, &cbNeeded))
          {
            pInfo->pPrintProcessor = gszPrintProc;
            SetPrinter(hPrinter, 2, (LPBYTE) pInfo, 0);
          }
          else 
          {
            bRet = FALSE;
          }
          if (pInfo)
          {
            LocalFree(pInfo);
          }
        }
        ClosePrinter(hPrinter);
      }
      else  // OpenPrinter failed
      {
        bRet = FALSE;
      }
    break;
    // cases for other events

    default:
      break;
  }  // end switch
  return bRet;
}

Связывание обработчика печати с очередью печати во время обновления драйвера принтера

При обновлении драйвера принтера обработчик печати обновленной очереди печати не изменяется. Если новому драйверу принтера требуется определенный процессор печати, функция DrvUpgradePrinter интерфейса принтера должна задать для элемента pPrintProcessor структуры PRINTER_INFO_2 имя нового процессора печати. После этого эта функция вызывает SetPrinter для обновления параметров принтера. Диспетчер очереди вызывает функцию DrvUpgradePrinter один раз для каждого принтера, что гарантирует, что все принтеры, использующие этот драйвер, также используют необходимый процессор печати. Эти моменты демонстрируются в следующем примере кода.

BOOL
DrvUpgradePrinter(
                 DWORD   Level,
                 LPBYTE  pDriverUpgradeInfo
                 )
{
  HANDLE                  hPrinter;
  PRINTER_DEFAULTS        PrinterDef = {NULL, NULL, PRINTER_ALL_ACCESS};
 PDRIVER_UPGRADE_INFO_2  pDUI2;
  LPPRINTER_INFO_2        pInfo = NULL;
 DWORD                   cbNeeded;
  TCHAR                   gszPrintProc[]   = TEXT("<Print processor name>");
  TCHAR                   gszPrintDriver[] = TEXT("<Printer driver name>");
  BOOL                    bRet = TRUE;

  if ((Level == 2)                                            &&
      (pDUI2 = (PDRIVER_UPGRADE_INFO_2)pDriverUpgradeInfo)    &&
      (OpenPrinter(pDUI2->pPrinterName, &hPrinter, &PrinterDef)))
  {
    if ( !GetPrinter( hPrinter, 2, (LPBYTE) pInfo, 0, &cbNeeded )  &&
         (GetLastError() != ERROR_INSUFFICIENT_BUFFER) )
    {
       bRet = FALSE;
    }
    if (bRet == TRUE)
    {
      pInfo = (LPPRINTER_INFO_2) LocalAlloc(LPTR, cbNeeded);
      bRet = pInfo ? TRUE : FALSE;
    }
    if (bRet == TRUE)
    {
      if (GetPrinter(hPrinter, 2, (LPBYTE) pInfo, cbNeeded, &cbNeeded))
      {
      //
      // This function is called for every printer queue that uses a driver
      // for which one or more files were updated. However, we only want to
      // update the printer queue's "driver" by a particular driver.
      //
      if ( !lstrcmpi(pInfo->pDriverName, gszPrintDriver) )
      {
        pInfo->pPrintProcessor =  gszPrintProc;
        SetPrinter(hPrinter, 2, (LPBYTE) pInfo, 0);
      }
    else  // GetPrinter 
    {
      bRet = FALSE;
    }
    if (pInfo)
    {
      LocalFree(pInfo);
    }
    ClosePrinter(hPrinter);
  }
  else  // Level != 2 or pDUI2 == NULL or OpenPrinter failed
  {
    bRet = FALSE;
  }
  return bRet;
}