Impressao - todas as informacoes sobre as impressoras (porta, rede, nomes)

Top  Previous  Next

{-----------------------------------------------------------------------------------------

  Esta funcao foi uma das mais suadas de todos os tempos, eu peguei N exemplos na NET  para

  poder capturar o nome da impressora compartilhada no NT/2K, e nada. O Printers.GetPrinter

  não trazia as informações necesárias no NT, só no 9x. Então eu tive que  suar a  camisa e

  depois de mais de 6 meses ( e muitas desistencias )  cheguei a ela:  GetPrinterParams ela

  usa uma API que retorna informacoes das impressoras instaladas de forma diferente no NT e

  no 9x.  Usei um " truque " para saber se a impressora é local ou de rede.  Mas para ficar

  100% eu criei um type com nome,  porta e se é em rede e 2 variaveis uma contem uma matriz

  com as informacoes de todas as impressoras e outra a quantidade de impressoras.

  Se voce está usando esta funcao hoje, quero que saiba que deve muito a mim. Te digo:  nao

  foi facil.

 

  Autor: Flávio Junior

  Data : do início de 2000 e termino em 05 de janeiro de 2001 - sexta

         (falta 1 semana pra eu sair de férias, beleza)

 

        >\\\!/<

        !_"""_!

        (O) (o)

------ooo-----ooo------------------------------------------------------------------------}

 

type

  TPrinterParamsA = record  // tipo que armazena informacoes individuais das impressoras

    Nome : string;

    Porta: string;

    Rede : Boolean;

  end;

 

var

  PrinterParams     : array of TPrinterParamsA;  // matriz que contem info de todas as impressoras do Windows

  PrinterParamsCount: Integer;                   // var que marca quantas impressoras tem.

 

// funcao propriamente dita

procedure GetPrintersParams;

var

  LineCur, Port        : PChar;

  Buffer, PrinterInfo  : PChar;

  Flags, Count, NumInfo: DWORD;

  I                    : Integer;

  Level                : Byte;

 

  // Esta funcao é usado para separar a porta no Windows NT

  function FetchStr(var Str: PChar): PChar;

  var

    P: PChar;

  begin

    Result := Str;

    if Str = nil then Exit;

    P := Str;

    while P^ = ' ' do Inc(P);

    Result := P;

    while (P^ <> #0and (P^ <> ',') do Inc(P);

    if P^ = ',' then

    begin

      P^ := #0;

      Inc(P);

    end;

    Str := P;

  end;

begin

  // dependendo do Window parametros diferentes (NT / 9x)

  if Win32Platform = VER_PLATFORM_WIN32_NT then

  begin

    Flags := PRINTER_ENUM_LOCAL or PRINTER_ENUM_CONNECTIONS {or PRINTER_ENUM_SHARED};

    Level := 2;

  end

  else

  begin

    Flags := PRINTER_ENUM_LOCAL;

    Level := 5;

  end;

  Count := 0;

  EnumPrinters(Flags, nil, Level, nil, 0Count, NumInfo); // Pega lista das impressoras

  if Count = 0 then Exit// Nenhuma? cai fora...

  GetMem(Buffer, Count);  // Separa memoria para o Buffer

  try

    if not EnumPrinters(Flags, nil, Level, PByte(Buffer), CountCount, NumInfo) then Exit;

    PrinterInfo        := Buffer;      // Tá aki as infos!

    PrinterParamsCount := NumInfo;     // Esta é uma variavel global retorna o numero de impressoras

    SetLength(PrinterParams, NumInfo); // Define o tamanho da matriz

    for I := 0 to NumInfo - 1 do       // Percorre todas as impressoras

    begin

      if Level = 5 then // é Level 5 (Win9x)?

        with PPrinterInfo5(PrinterInfo)^ do

        begin

          PrinterParams[I].Nome  := pPrinterName;

          PrinterParams[I].Porta := pPortName;

          PrinterParams[I].Rede  := Pos('\\', pPortName) > 0;

          Inc(PrinterInfo, SizeOf(TPrinterInfo5));

        end

      else // WinNT/2000

        with PPrinterInfo2(PrinterInfo)^ do

        begin

          LineCur  := pPortName;

          Port     := FetchStr(LineCur);

          while Port^ <> #0 do // quando peguei o exemplo já tinha isso, nao sei exatamente o que é. Mas funciona

          begin

            PrinterParams[I].Nome  := pPrinterName;

            if Trim(pServerName) = '' then  // caso o windows não retorne o nome da rede...

            begin

              if Pos('\\',pPrinterName) > 0 then // ...mas tem duas barras na descricao...

                PrinterParams[I].Porta := pPrinterName  // ...a porta é a descricao.

              else

                PrinterParams[I].Porta := 'LPT1'        // se não tem porta e não tem \\ na descricao é impressora local

            end

            else

              PrinterParams[I].Porta := pServerName + '\' + pShareName;  // de rede

            PrinterParams[I].Rede  := Pos( '\\', PrinterParams[I].Nome) > 0;

            Port := FetchStr(LineCur);

          end;

          Inc(PrinterInfo, SizeOf(TPrinterInfo2));

        end;

    end// for

  finally

    FreeMem(Buffer, Count); // Libera memoria separada para o Buffer

  end;

end;

 

procedure TForm1.Button2Click(Sender: TObject);

var

  I: Integer;

begin

  GetPrintersParams;

  Grid.RowCount := PrinterParamsCount + 1;

  for I := 0 to PrinterParamsCount-1 do

  begin

    Grid.Cells[0, I+1] := PrinterParams[I].Nome;

    Grid.Cells[1, I+1] := PrinterParams[I].Porta;

    if PrinterParams[I].Rede then

      Grid.Cells[2, I+1] := 'EM REDE'

    else

      Grid.Cells[2, I+1] := 'LOCAL';

  end;

  ListBox1.Items := Printer.Printers;

end;

 

 

procedure TForm1.Button1Click(Sender: TObject);

begin

  Close;

end;

 

procedure SetPadrao;

var

  Res         : DWORD;

  Device      : array[0..255of char;

  Driver      : array[0..255of char;

  Port        : array[0..255of char;

  WindowsStr  : array[0..255of char;

  hDeviceMode : THandle;

begin

  // Pega dados da impressora atual

  Printer.GetPrinter(Device, Driver, Port, hDeviceMode);

  // Monta string exigida pela API do Windows

  StrCat( Device, ',');

  StrCat( Device, Driver );

  StrCat( Device, ',');

  StrCat( Device, Port );

  StrPCopy(WindowsStr, 'windows');

  // Torna a impressora a atual;

  WriteProfileString(WindowsStr, 'device', Device);

  SendMessageTimeout(HWND_BROADCAST, WM_WININICHANGE, 0, DWORD(@WindowsStr), SMTO_NORMAL, 1000, Res);

end;

 

// Teste de impressao

procedure TForm1.Button3Click(Sender: TObject);

var

  F        : TextFile;

  Porta    : string;

  OldPadrao: Integer;

begin

  Porta:= Grid.Cells[1, Grid.Row];

  // Imprime normal para a porta

  AssignFile(F, Porta);

  Rewrite(F);

  Writeln(F,'TESTE IMPRESSAO');

  if Win32Platform = VER_PLATFORM_WIN32_WINDOWS        then Writeln(F,#12); // No Win9x usa o FormFeed.

  CloseFile(F);

 

  // No WinNT/2K a impressora aceita o FormFeed e Tear-off

  if Win32Platform = VER_PLATFORM_WIN32_NT then

  begin

    // Para fazer o TEAR-OFF tem que fechar a porta como sendo impressora padrão Windows

    OldPadrao            := Printer.PrinterIndex;

    Printer.PrinterIndex := Printer.Printers.IndexOf( Grid.Cells[0, Grid.Row] );

    Caption := Printer.Printers[ Printer.PrinterIndex ];

    SetPadrao;

    Sleep(100);

 

    AssignPrn(F);

    Rewrite(F);

    System.CloseFile(F);

 

    // Volta o padrão antigo

    Printer.PrinterIndex := OldPadrao;

    SetPadrao;

  end;

end;