FAQ VCL
Железо\Принтер

:: Меню ::
:: На главную ::
:: FAQ ::
:: Заметки ::
:: Практика ::
:: Win API ::
:: Проекты ::
:: Скачать ::
:: Секреты ::
:: Ссылки ::

:: Сервис ::
:: Написать ::

:: MVP ::

:: RSS ::

Яндекс.Метрика

Как проверить, установлен ли принтер "по умолчанию"?

uses
  {...,} Printers;

procedure TForm1.Button1Click(Sender: TObject);
var
  Device, Driver, Port: array [0..255] of Char;
  Mode: Cardinal;
begin
   Printer.GetPrinter( Device, Driver, Port, Mode );
   if Device <> '' then
      ShowMessage( Device )
   else
      ShowMessage( 'Не установлен принтер по умолчанию' );
end;


Как определить статус печати документов принтера "по умолчанию"?

// Способ первый
unit PrintStatus;

interface

  function PrinterStatus( var aStatus: LongWord; var aNrJobs: Integer ): string;

implementation

uses
  Windows, SysUtils, Printers, WinSpool;

resourcestring
  rsNrJobsWaiting = '%0:u document(s) waiting';
  rsStatusSep = '; ';

  rsStatusIdle = 'Idle';
  rsStatusUnknown = 'Unknown';
  rsStatusBusy = 'Busy';
  rsStatusDoorOpen = 'Door open';
  rsStatusError = 'Error';
  rsStatusInitializing = 'Initialising';
  rsStatusIOActive = 'I/O active';
  rsStatusManualFeed = 'Manual feed';
  rsStatusNoToner = 'No toner';
  rsStatusNotAvailable = 'Not available';
  rsStatusOffline = 'Offline';
  rsStatusOutOfMemory = 'Out of memory';
  rsStatusOutputBinFull = 'Output bin full';
  rsStatusPagePunt = 'Page punt';
  rsStatusPaperJam = 'Paper jam';
  rsStatusPaperOut = 'Paper out';
  rsStatusPaperProblem = 'Paper problem';
  rsStatusPaused = 'Paused';
  rsStatusPendingDeletion = 'Pending deletion';
  rsStatusPowerSave = 'Power-save';
  rsStatusPrinting = 'Printing';
  rsStatusProcessing = 'Processing';
  rsStatusServerUnknown = 'Server unknown';
  rsStatusTonerLow = 'Toner low';
  rsStatusUserIntervention = 'User intervention';
  rsStatusWaiting = 'Waiting';
  rsStatusWarmingUp = 'Warming up';

function PrinterStatus( var aStatus: LongWord; var aNrJobs: Integer ): string;

  procedure AddStatus( aStr: string );
  begin
     if Result <> '' then
        Result := Result + rsStatusSep;
     Result := Result + aStr;
  end;

  function NewStatus( var aNJ: Integer ): LongWord;
  var
    Count: LongWord;
    DevName: string;
    hPrinter: THandle;
    JobInfoCount: LongWord;
    JobInfo2: PJobInfo2;
    PrinterInfo2: PPrinterInfo2;
  begin
     Result := 0;
     DevName := Printer.Printers[Printer.PrinterIndex];

     if OpenPrinter( PChar( DevName ), hPrinter, nil ) then
     begin
        Count := 0;
        GetPrinter( hPrinter, 2, nil, 0, @Count );

        if Count > 0 then
        begin
           GetMem( PrinterInfo2, Count );
           GetPrinter( hPrinter, 2, PrinterInfo2, Count, @Count );
           Result := PrinterInfo2.Status;
           aNJ := PrinterInfo2.cJobs;
           FreeMem( PrinterInfo2 );

           if aNJ > 0 then
           begin
              Count := 0;
              EnumJobs( hPrinter, 0, 1, 2, nil, 0, Count, JobInfoCount );

              if Count > 0 then
              begin
                 GetMem( JobInfo2, Count );
                 EnumJobs( hPrinter, 0, 1, 2, JobInfo2, Count, Count, JobInfoCount );
                 if ( JobInfoCount > 0 ) and ( JobInfo2.Status <> 0 ) then
                 begin
                    if ( JobInfo2.Status and JOB_STATUS_BLOCKED_DEVQ ) <> 0 then
                       Result := Result or PRINTER_STATUS_ERROR;
                    if ( JobInfo2.Status and JOB_STATUS_DELETING ) <> 0 then
                       Result := Result or PRINTER_STATUS_PENDING_DELETION;
                    if ( JobInfo2.Status and JOB_STATUS_ERROR ) <> 0 then
                       Result := Result or PRINTER_STATUS_ERROR;
                    if ( JobInfo2.Status and JOB_STATUS_OFFLINE ) <> 0 then
                       Result := Result or PRINTER_STATUS_OFFLINE;
                    if ( JobInfo2.Status and JOB_STATUS_PAPEROUT ) <> 0 then
                       Result := Result or PRINTER_STATUS_PAPER_OUT;
                    if ( JobInfo2.Status and JOB_STATUS_PAUSED ) <> 0 then
                       Result := Result or PRINTER_STATUS_PAUSED;
                    if ( JobInfo2.Status and ( JOB_STATUS_PRINTING or JOB_STATUS_RESTART ) ) <> 0 then
                       Result := Result or PRINTER_STATUS_PRINTING;
                    if (JobInfo2.Status and JOB_STATUS_USER_INTERVENTION) <> 0 then
                       Result := Result or PRINTER_STATUS_USER_INTERVENTION;
                 end;
                 FreeMem( JobInfo2 );
              end;
           end;
        end;
        ClosePrinter( hPrinter );
     end;
  end;

begin
   Result := '';
   aNrJobs := 0;
   aStatus := NewStatus( aNrJobs );
   if aStatus = 0 then
   begin
      if aNrJobs > 0 then
         Result := rsStatusPrinting
      else
         Result := rsStatusIdle;
   end
   else
   begin
      if ( aStatus and PRINTER_STATUS_BUSY <> 0 ) then
         AddStatus( rsStatusBusy );
      if ( aStatus and PRINTER_STATUS_DOOR_OPEN <> 0 ) then
         AddStatus( rsStatusDoorOpen );
      if ( aStatus and PRINTER_STATUS_ERROR <> 0 ) then
         AddStatus( rsStatusError );
      if ( aStatus and PRINTER_STATUS_INITIALIZING <> 0 ) then
         AddStatus( rsStatusInitializing );
      if ( aStatus and PRINTER_STATUS_IO_ACTIVE <> 0 ) then
         AddStatus( rsStatusIOActive );
      if ( aStatus and PRINTER_STATUS_MANUAL_FEED <> 0 ) then
         AddStatus( rsStatusManualFeed );
      if ( aStatus and PRINTER_STATUS_NO_TONER <> 0 ) then
         AddStatus( rsStatusNoToner );
      if ( aStatus and PRINTER_STATUS_NOT_AVAILABLE <> 0 ) then
         AddStatus( rsStatusNotAvailable );
      if ( aStatus and PRINTER_STATUS_OFFLINE <> 0 ) then
         AddStatus( rsStatusOffline );
      if ( aStatus and PRINTER_STATUS_OUT_OF_MEMORY <> 0 ) then
         AddStatus( rsStatusOutOfMemory );
      if ( aStatus and PRINTER_STATUS_OUTPUT_BIN_FULL <> 0 ) then
         AddStatus( rsStatusOutputBinFull );
      if ( aStatus and PRINTER_STATUS_PAGE_PUNT <> 0 ) then
         AddStatus( rsStatusPagePunt );
      if ( aStatus and PRINTER_STATUS_PAPER_JAM <> 0 ) then
         AddStatus( rsStatusPaperJam );
      if ( aStatus and PRINTER_STATUS_PAPER_OUT <> 0 ) then
         AddStatus( rsStatusPaperOut );
      if ( aStatus and PRINTER_STATUS_PAPER_PROBLEM <> 0 ) then
         AddStatus( rsStatusPaperProblem );
      if ( aStatus and PRINTER_STATUS_PAUSED <> 0 ) then
         AddStatus( rsStatusPaused );
      if ( aStatus and PRINTER_STATUS_PENDING_DELETION <> 0 ) then
         AddStatus( rsStatusPendingDeletion );
      if ( aStatus and PRINTER_STATUS_POWER_SAVE <> 0 ) then
         AddStatus( rsStatusPowerSave );
      if ( aStatus and PRINTER_STATUS_PRINTING <> 0 ) then
         AddStatus( rsStatusPrinting );
      if ( aStatus and PRINTER_STATUS_PROCESSING <> 0 ) then
         AddStatus( rsStatusProcessing );
      if ( aStatus and PRINTER_STATUS_SERVER_UNKNOWN <> 0 ) then
         AddStatus( rsStatusServerUnknown );
      if ( aStatus and PRINTER_STATUS_TONER_LOW <> 0 ) then
         AddStatus( rsStatusTonerLow );
      if ( aStatus and PRINTER_STATUS_USER_INTERVENTION <> 0 ) then
         AddStatus( rsStatusUserIntervention );
      if ( aStatus and PRINTER_STATUS_WAITING <> 0 ) then
         AddStatus( rsStatusWaiting );
      if ( aStatus and PRINTER_STATUS_WARMING_UP <> 0 ) then
         AddStatus( rsStatusWarmingUp );
   end;
   if aNrJobs > 0 then
      Result := Result + rsStatusSep + Format( rsNrJobsWaiting, [aNrJobs] );
end;

end.

{...}

procedure TForm1.Button1Click(Sender: TObject);
var
  Status: Cardinal;
  NrJobs: Integer;
  s: string;
begin
   s := PrinterStatus( Status, NrJobs );
   ShowMessage( s + #13 + IntToStr( Status ) + #13 + IntToStr( NrJobs ) );
end;

// Способ второй
unit PrintStatus;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, StdCtrls, WinSpool, Generics.Collections, Menus{, WinSock};

type
  PTMibTCPRow = ^TMibTCPRow;
  TMibTCPRow = packed record
    dwState: DWORD;
    dwLocalAddr: DWORD;
    dwLocalPort: DWORD;
    dwRemoteAddr: DWORD;
    dwRemotePort: DWORD;
  end;

  PTMibTCPTable = ^TMibTCPTable;
  TMibTCPTable = packed record
    dwNumEntries: DWORD;
    Table: array[0..0] of TMibTCPRow;
  end;

  TProcessEntry32 = packed record
    dwSize: DWORD;
    cntUsage: DWORD;
    th32ProcessID: DWORD;
    th32DefaultHeapID: DWORD;
    th32ModuleID: DWORD;
    cntThreads: DWORD;
    th32ParentProcessID: DWORD;
    pcPriClassBase: Longint;
    dwFlags: DWORD;
    szExeFile: array [0..MAX_PATH - 1] of WideChar;
  end;

  JOB_INFO_1_ARRAY = array [0..0] of JOB_INFO_1;

  function GetTcpTable(var pTCPTable: PTMibTCPTable; var pDWSize: PDWORD;
    bOrder: BOOL): DWORD; stdcall; external 'IPHLPAPI.DLL';

var
  JobList: TList< JOB_INFO_1 >;

  procedure JobToListView( Job: JOB_INFO_1; var List: TStrings );
  function ListJobOfPrinter( PrinterName: AnsiString ): Boolean;

implementation

uses
  Printers;

//const
//  // Константы состояний порта
//  MIB_TCP_STATE_CLOSED     = 1;
//  MIB_TCP_STATE_LISTEN     = 2;
//  MIB_TCP_STATE_SYN_SENT   = 3;
//  MIB_TCP_STATE_SYN_RCVD   = 4;
//  MIB_TCP_STATE_ESTAB      = 5;
//  MIB_TCP_STATE_FIN_WAIT1  = 6;
//  MIB_TCP_STATE_FIN_WAIT2  = 7;
//  MIB_TCP_STATE_CLOSE_WAIT = 8;
//  MIB_TCP_STATE_CLOSING    = 9;
//  MIB_TCP_STATE_LAST_ACK   = 10;
//  MIB_TCP_STATE_TIME_WAIT  = 11;
//  MIB_TCP_STATE_DELETE_TCB = 12;

//// Функция преобразует состояние порта в строковый эквивалент
//function PortStateToStr( const State: DWORD ): String;
//begin
//   case State of
//      MIB_TCP_STATE_CLOSED: Result := 'CLOSED';
//      MIB_TCP_STATE_LISTEN: Result := 'LISTEN';
//      MIB_TCP_STATE_SYN_SENT: Result := 'SYN SENT';
//      MIB_TCP_STATE_SYN_RCVD: Result := 'SYN RECEIVED';
//      MIB_TCP_STATE_ESTAB: Result := 'ESTABLISHED';
//      MIB_TCP_STATE_FIN_WAIT1: Result := 'FIN WAIT 1';
//      MIB_TCP_STATE_FIN_WAIT2: Result := 'FIN WAIT 2';
//      MIB_TCP_STATE_CLOSE_WAIT: Result := 'CLOSE WAIT';
//      MIB_TCP_STATE_CLOSING: Result := 'CLOSING';
//      MIB_TCP_STATE_LAST_ACK: Result := 'LAST ACK';
//      MIB_TCP_STATE_TIME_WAIT: Result := 'TIME WAIT';
//      MIB_TCP_STATE_DELETE_TCB: Result := 'DELETE TCB';
//   else
//      Result := 'UNKNOWN';
//   end;
//end;

function GetStatus( Job: JOB_INFO_1 ): AnsiString;
begin
   case Job.Status of
      JOB_STATUS_PAUSED: result := 'JOB_STATUS_PAUSED';
      JOB_STATUS_ERROR: result := 'JOB_STATUS_ERROR';
      JOB_STATUS_DELETING: result := 'JOB_STATUS_DELETING';
      JOB_STATUS_SPOOLING: result := 'JOB_STATUS_SPOOLING';
      JOB_STATUS_PRINTING: result := 'JOB_STATUS_PRINTING';
      JOB_STATUS_OFFLINE: result := 'JOB_STATUS_OFFLINE';
      JOB_STATUS_PAPEROUT: result := 'JOB_STATUS_PAPEROUT';
      JOB_STATUS_PRINTED: result := 'JOB_STATUS_PRINTED';
      JOB_STATUS_DELETED: result := 'JOB_STATUS_DELETED';
      JOB_STATUS_BLOCKED_DEVQ: result := 'JOB_STATUS_BLOCKED_DEVQ';
      JOB_STATUS_USER_INTERVENTION: result := 'JOB_STATUS_USER_INTERVENTION';
      JOB_STATUS_RESTART: result := 'JOB_STATUS_RESTART';
      JOB_POSITION_UNSPECIFIED: result := 'JOB_POSITION_UNSPECIFIED';
      else
         Result := 'Unknown status...';
   end;
end;

procedure GetPortStats;
var
  Size: PDWORD;
  i: DWORD;
  TCPTable: PTMibTCPTable;
begin
   GetMem( TCPTable, SizeOf( TMibTCPTable ) );
   try
      Size := 0;
   finally
      FreeMem( TCPTable );
   end;
//   GetMem( TCPTable, Size^ );
//   try
//      if GetTcpTable( TCPTable, Size, True ) = NO_ERROR then
//      begin
//         for i := 0 to TCPTable^.dwNumEntries-1 do
//            Memo1.Lines.Add( Format( '%15s: | %5d %s', [inet_ntoa( in_addr( TCPTable^.Table[i].dwLocalAddr ) ),
//                                                        htons( TCPTable^.Table[i].dwLocalPort ),
//                                                        PortStateToStr( TCPTable^.Table[i].dwState )] ) );
//      end;
//   finally
//      FreeMem( TCPTable );
//   end;
end;

procedure JobToListView(Job: JOB_INFO_1; var List: TStrings);
var
  lv: TListItem;
begin
   List.Clear;
   List.Add( IntToStr( Job.JobId ) );
   List.Add( Job.pPrinterName );
   List.Add( Job.pMachineName );
   List.Add( Job.pUserName );
   List.Add( Job.pDocument );
   List.Add( Job.pDatatype );
   List.Add( GetStatus( Job ) );
   List.Add( IntToStr( Job.TotalPages ) );
   List.Add( IntToStr( Job.PagesPrinted ) );
   List.Add( DateTimeToStr( SystemTimeToDateTime( Job.Submitted ) ) );
end;

function ListJobOfPrinter( PrinterName: AnsiString ): Boolean;
var
  hPrinter: THandle;
  dwNeeded, dwReturned: DWORD;
  i: integer;
  PJobInfo: ^JOB_INFO_1_ARRAY;
begin
   if not OpenPrinterA( PAnsiChar( PrinterName ), hPrinter, nil ) then
   begin
      Result := False;
      Exit;
   end;
   if not EnumJobs( hPrinter, 0, $FFFFFFFF, 1, nil, 0, dwNeeded, dwReturned ) then
   begin
      if( GetLastError <> ERROR_INSUFFICIENT_BUFFER ) then
      begin
         ClosePrinter( hPrinter );
         Result := False;
         Exit;
      end;
   end;
   try
      GetMem( PJobInfo, SizeOf( JOB_INFO_1 ) * dwNeeded );
      if not EnumJobs( hPrinter, 0, $FFFFFFFF, 1, LPBYTE( pJobInfo ),
                       dwNeeded, dwNeeded, dwReturned ) then
      begin
         ClosePrinter( hPrinter );
         Result := False;
      end;
      for i := 0 to dwReturned-1 do
         JobList.Add( PJobInfo[i] );
   finally
      ClosePrinter( hPrinter );
      FreeMem( PJobInfo );
   end;
end;

initialization
  JobList := TList< JOB_INFO_1 >.Create;

finalization
  JobList.Free;

end.

{...}

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls, PrintStatus;

type
  TForm1 = class(TForm)
    ComboBox1: TComboBox;
    ListView1: TListView; // ViewStyle = vsReport, 10 колонок
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses
  Printers;

procedure TForm1.FormCreate(Sender: TObject);
begin
   ComboBox1.Items.Assign( Printer.Printers );
   Combobox1.ItemIndex := 0;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 i, j: Integer;
 sl: TStrings;
 li: TListItem;
begin
   if ListJobOfPrinter( ComboBox1.Items[ComboBox1.ItemIndex] ) then
   begin
      ListView1.Items.BeginUpdate;
      sl := TStringList.Create;
      for i := 0 to JobList.Count-1 do
      begin
         JobToListView( JobList[i], sl );
         li := ListView1.Items.Add;
         li.Caption := sl[0];
         for j := 1 to sl.Count-1 do
            li.SubItems.Add( sl[j] );
      end;
      ListView1.Items.EndUpdate;
      sl.Free;
   end;
end;

end.

При использовании материала - ссылка на сайт обязательна