Delphi World - Проверить, печатает ли текущий принтер в цвете
Delphi World - это проект, являющийся сборником статей и малодокументированных возможностей  по программированию в среде Delphi. Здесь вы найдёте работы по следующим категориям: delphi, delfi, borland, bds, дельфи, делфи, дэльфи, дэлфи, programming, example, программирование, исходные коды, code, исходники, source, sources, сорцы, сорсы, soft, programs, программы, and, how, delphiworld, базы данных, графика, игры, интернет, сети, компоненты, классы, мультимедиа, ос, железо, программа, интерфейс, рабочий стол, синтаксис, технологии, файловая система...
Проверить, печатает ли текущий принтер в цвете

Автор: Slava Vitebski
WEB-сайт: http://monfort.co.il


uses 
  Printers, WinSpool; 

procedure TForm1.Button1Click(Sender: TObject); 
var 
  Dev, Drv, Prt: array[0..255] of Char; 
  DM1: PDeviceMode; 
  DM2: PDeviceMode; 
  Sz: Integer; 
  DevM: THandle; 
begin 
  Printer.PrinterIndex := -1; 
  Printer.GetPrinter(Dev, Drv, Prt, DevM); 
  DM1 := nil; 
  DM2 := nil; 
  Sz  := DocumentProperties(0, 0, Dev, DM1^, DM2^, 0); 
  GetMem(DM1, Sz); 
  DocumentProperties(0, 0, Dev, DM1^, DM2^, DM_OUT_BUFFER); 
  if DM1^.dmColor > 1 then 
    label1.Caption := Dev + ': Color' 
  else 
    label1.Caption := Dev + ': Black and White'; 
  if DM1^.dmFields and DM_Color <> 0 then 
    Label2.Caption := 'Printer supports color printing' 
  else 
    Label2.Caption := 'Printer does not support color printing'; 
  FreeMem(DM1); 
end;

Недавно мне нужно было найти надёжный способ определить печатает ли принтер цветом или нет. Пример который приведен выше не подходит так как он использует API - DocumentProperties а эта функция возвращает положительный результат для чёрно-белых принтеров способных печатать оттенки серого цвета (пример такого принтера - HP LasetJet 1200). Быстры поиск привёл меня к функции - DeviceCapabilities (в Delphi она определена в WinSpool). Функция имеет следующий формат:

DWORD DeviceCapabilities(
  LPCTSTR pDevice,         // printer name
  LPCTSTR pPort,           // port name
  WORD fwCapability,       // device capability
  LPTSTR pOutput,          // output buffer
  CONST DEVMODE *pDevMode  // device data buffer
);

параметр fwCapability получает константу которая говорит о том что мы хотим узнать о принтере. В данном случае нас интересует DC_COLORDEVICE. MSDN пишет следующее о б этом параметре:

Windows 2000/XP: If the printer supports color printing, the return value is 1; otherwise, the return value is zero. The pOutput parameter is not used.

Не всё так просто. значение константы DC_COLORDEVICE определенно не верно!!! Заглянем в Windows.pas файл (это часть определений):

  DC_COLLATE = 22;
  {$EXTERNALSYM DC_MANUFACTURER}
  DC_MANUFACTURER = 23;
  {$EXTERNALSYM DC_MODEL}
  DC_MODEL = 24;
  {$EXTERNALSYM DC_COLORDEVICE}
  DC_COLORDEVICE = 23;
  {$EXTERNALSYM DC_NUP}
  DC_NUP = 24;
  {$EXTERNALSYM DC_PERSONALITY}
  DC_PERSONALITY = 25;

Обратите внимание на выделенные строчки, у них одинаковые значения. Похожая ситуация наблюдается во всех версиях Delphi и в Visual C++ 6. Только в Visual C++ 7 (Visual Studio .NET) Microsoft решили исправить ситуацию и дали нам правильные кода. Ну а вот собственно и сама функция:

uses
    Printers, WinSpool;

    const
         {Those constants definition is WRONG !!! in Delphi and "VC 6".
          Only in "VC 7" those definitions are corrected.}
         DC_PERSONALITY         = 25;
         DC_PRINTRATE              = 26;
         DC_PRINTRATEUNIT       = 27;
         DC_PRINTERMEM          = 28;
         DC_MEDIAREADY          = 29;
         DC_STAPLE                   = 30;
         DC_PRINTRATEPPM      = 31;
         DC_COLORDEVICE        = 32;
         DC_NUP                         = 33;
         DC_MEDIATYPENAMES = 34;
         DC_MEDIATYPES           = 35;

    function IsPrinterSupportColor(APtinterName: string): boolean;
    var
      fRes: Integer;
      pPrinterInfo: ^PRINTER_INFO_2;
      Needed: cardinal;
      phPrinter: cardinal;
    begin
         OpenPrinter(PChar(APtinterName), phPrinter, nil);
         GetPrinter(phPrinter, 2, nil, 0, @Needed);
         GetMem(pPrinterInfo, Needed);
         try
            GetPrinter(phPrinter, 2, pPrinterInfo, Needed, @Needed);

             fRes := WinSpool.DeviceCapabilities(pPrinterInfo^.pPrinterName,
              pPrinterInfo^.pPortName, DC_COLORDEVICE, nil, nil);
            if fRes = -1 then
               raise Exception.Create(SysErrorMessage(GetLastError));
            Result := fRes = 1;
         finally
            FreeMem(pPrinterInfo, Needed);
         end;
    end;
Проект Delphi World © Выпуск 2002 - 2017
Автор проекта: Эксклюзивные курсы программирования