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^ <> #0) and (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, 0, Count, 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), Count, Count, 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..255] of char; Driver : array[0..255] of char; Port : array[0..255] of char; WindowsStr : array[0..255] of 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; |