一些关于打印机的代码

      语言类学习笔记 2009-1-12 23:8

如何在程序里判断一个打印作业已经进入打印队列(也就是可以在打印管理程序里看到该作业的信息),或者说如何察看打印队列里已有的作业信息?  
   
  看下面的这个例程。还有测试代码。  
   
  uses   WinSpool;    
  type   JOB_INFO_1_ARRAY   =   Array   of   JOB_INFO_1;    
  Function   GetSpoolerJobs(sPrinterName   :   String)   :   JOB_INFO_1_ARRAY;    
  var    
  i   :   Integer;    
  hPrinter   :   THandle;    
  bResult   :   Boolean;    
  cbBuf   :   DWORD;    
  pcbNeeded   :   DWORD;    
  pcReturned   :   DWORD;    
  aJobs   :   Array[0..99]   of   JOB_INFO_1;    
  begin    
  cbBuf   :=   1000;    
   
  bResult   :=   OpenPrinter(PChar(sPrinterName),   hPrinter,   Nil);    
  if   NOT   bResult   then   begin    
  ShowMessage('Error   opening   the   printer');    
  exit;    
  end;    
   
  bResult   :=   EnumJobs(hPrinter,0,Length(aJobs),1,@aJobs,cbBuf,pcbNeeded,pcReturned);    
  if   NOT   bResult   then   begin    
  ShowMessage('Error   Getting   Jobs   information');    
  exit;    
  end;    
   
  for   i:=0   to   pcReturned-1   do   begin    
  if   aJobs[i].pDocument   <>   Nil   then   begin    
  SetLength(Result,   Length(Result)+1);    
  Result[Length(Result)-1]   :=   aJobs[i];    
  end;    
  end;    
  end;    
   
  测试例子:  
  1-   创建工程有   StringGrid   和一个   Timer.    
  2-   StringGrid   'ColCount'   and   “RowCount”   值为   20  
  3-   Timer的   “Interval”   属性值   500.    
  4-   “OnTime”   实践中写这个代码  
  procedure   TForm1.Timer1Timer(Sender:   TObject);    
  var    
  i,   ii   :   Integer;    
  aJobs   :   JOB_INFO_1_ARRAY;    
  begin    
  for   i:=0   to   StringGrid1.ColCount-1   do    
  for   ii:=0   to   StringGrid1.RowCount-1   do   StringGrid1.Cells[i,ii]   :=   '';    
   
  aJobs   :=   GetSpoolerJobs('\\ibmserver\HP   LaserJet   1100');//正在打印的打印机名字,这里我的打印机时网打。这里你要自己改  
   
  for   i:=0   to   Length(aJobs)-1   do   begin    
  StringGrid1.Cells[i,0]   :=   aJobs[i].pPrinterName;    
  StringGrid1.Cells[i,1]   :=   aJobs[i].pMachineName;    
  StringGrid1.Cells[i,2]   :=   aJobs[i].pUserName;    
  StringGrid1.Cells[i,3]   :=   aJobs[i].pDocument;    
  StringGrid1.Cells[i,4]   :=   aJobs[i].pDatatype;    
  StringGrid1.Cells[i,5]   :=   aJobs[i].pStatus;    
  StringGrid1.Cells[i,6]   :=   IntToStr(aJobs[i].Status);    
   
  case   aJobs[i].Status   of    
  JOB_STATUS_PAUSED:   StringGrid1.Cells[i,6]   :=   'JOB_STATUS_PAUSED';    
  JOB_STATUS_ERROR:   StringGrid1.Cells[i,6]   :=   'JOB_STATUS_ERROR';    
  JOB_STATUS_DELETING:   StringGrid1.Cells[i,6]   :=   'JOB_STATUS_DELETING';    
  JOB_STATUS_SPOOLING:   StringGrid1.Cells[i,6]   :=   'JOB_STATUS_SPOOLING';    
  JOB_STATUS_PRINTING:   StringGrid1.Cells[i,6]   :=   'JOB_STATUS_PRINTING';    
  JOB_STATUS_OFFLINE:   StringGrid1.Cells[i,6]   :=   'JOB_STATUS_OFFLINE';    
  JOB_STATUS_PAPEROUT:   StringGrid1.Cells[i,6]   :=   'JOB_STATUS_PAPEROUT';    
  JOB_STATUS_PRINTED:   StringGrid1.Cells[i,6]   :=   'JOB_STATUS_PRINTED';    
  JOB_STATUS_DELETED:   StringGrid1.Cells[i,6]   :=   'JOB_STATUS_DELETED';    
  JOB_STATUS_BLOCKED_DEVQ:   StringGrid1.Cells[i,6]   :=   'JOB_STATUS_BLOCKED_DEVQ';    
  JOB_STATUS_USER_INTERVENTION:   StringGrid1.Cells[i,6]   :=   'JOB_STATUS_USER_INTERVENTION';    
  JOB_STATUS_RESTART:   StringGrid1.Cells[i,6]   :=   'JOB_STATUS_RESTART';    
  JOB_POSITION_UNSPECIFIED:   StringGrid1.Cells[i,6]   :=   'JOB_POSITION_UNSPECIFIED';    
   
  else   StringGrid1.Cells[i,6]   :=   'Unknown   status...';    
  end;    
  end;    
   
  StringGrid1.Refresh;    
  end;    
   
  5-   运行程序,打印程序测之  

为默认打印机创建一个快捷方式后,用ShellExecute运行可以启动默认  
  打印机管理程序。如果不创建快捷方式,如何直接启动。  
  感谢http://www.experts-exchange.com/Q.10115433,   以下代码ShowPrintSpool可以实现:  
  function   ExecuteContextMenuCommand(hParent:   THandle;   sf:   IShellFolder;   childPidl:   PItemIDList;  
      verb:   string   =   '';   propPage:   string   =   '';   pidlCount:   UInt   =   1):   Boolean;  
  var  
      cm,   cm2,   cm3:   IContextMenu;  
      ici:   TCMInvokeCommandInfo;  
      pop   :   HMenu;  
      c:   Cardinal;  
  begin  
      Result   :=   False;  
      if   sf.GetUIObjectOf(hParent,   pidlCount,   childPidl,   IID_IContextMenu,nil,   Pointer(cm))   <>   NOERROR   then   Exit;  
      try  
          cm2   :=   cm   as   IContextMenu2;  
          cm   :=   cm2;  
          try  
              cm3   :=   cm   as   IContextMenu3;  
              cm   :=   cm3;  
          except  
          end;  
      except  
      end;  
      ZeroMemory(@ici,   sizeOf(ici));  
      with   ici   do  
      begin  
          cbSize   :=   sizeOf(TCMInvokeCommandInfo);  
          fMask   :=   CMIC_MASK_FLAG_NO_UI;  
          hWnd   :=   hParent;  
          lpVerb   :=   PChar(verb);  
          lpParameters   :=   PChar(propPage);   //'Settings';  
          nShow   :=   SW_SHOW;  
      end;  
      if   verb   <>   ''   then  
          Result   :=   cm.InvokeCommand(ici)   =   NOERROR  
      else  
      begin  
          pop   :=   CreatePopupMenu;  
          try  
              if   Succeeded(cm.QueryContextMenu(pop,   0,   1,   $ 7FFF,   CMF_DEFAULTONLY))   then  
              begin  
                  c   :=   GetMenuDefaultItem(pop,   0,   0);  
                  if   c   <>   0   then  
                  begin  
                      ici.lpVerb   :=   MakeIntResource(c   -   1);  
                      Result   :=   cm.InvokeCommand(ici)   =   NOERROR;  
                  end;  
              end;  
          finally  
              DestroyMenu(pop)  
          end;  
      end  
  end;  
   
  function   PidlToStr(sf:   IShellFolder;   childPidl:   PItemIDList):   string;  
  var  
      sr:   _StrRet;  
  begin  
      Result   :=   '';  
      if   (sf   =   nil)   or   (childPidl   =   nil)   then   Exit;  
      sr.uType   :=   STRRET_CSTR;  
      if   sf.GetDisplayNameOf(childPidl,SHGDN_NORMAL,sr)   =   NOERROR   then  
          case   sr.uType   of  
              STRRET_CSTR       :   Result   :=   string(sr.cStr);  
              STRRET_OFFSET   :   Result   :=   string(PChar(Cardinal(childPidl)   +   sr.uOffset));  
              STRRET_WSTR       :   Result   :=   string(sr.pOleStr);  
          end;  
  end;  
   
  function   DefaultPrinterDevice:   string;  
  var  
      Device,   Driver,   Port:   array   [0..255]   of   Char;  
      Mode:   THandle;  
  begin  
      Device   :=   '';  
      with   Printer   do  
          if   Printers.Count   >   0   then  
              GetPrinter(Device,   Driver,   Port,   Mode);  
      Result   :=   Device;  
  end;  
   
  procedure   ShowPrintSpool;  
  var  
      pidl1,   pidl2:   PItemIDList;  
      sf1,   sf2:   IShellFolder;  
      malloc:   IMalloc;  
      el:   IEnumIDList;  
      c:   Cardinal;  
      sDefaultPrinter:   string;  
  begin  
      if   (SHGetSpecialFolderLocation(INVALID_HANDLE_VALUE,   CSIDL_PRINTERS,   pidl1)   =   NOERROR)   and  
          (SHGetMalloc(malloc)   =   NOERROR)   then  
          try  
              if   (pidl1^.mkid.cb   <>   0)   and   (SHGetDesktopFolder(sf1)   =   NOERROR)   and  
                  (sf1.BindToObject(pidl1,   nil,   IID_IShellFolder,   Pointer(sf2))   =   NOERROR)   and  
                  (sf2.EnumObjects(Application.Handle,   High(Cardinal),   el)   =   NOERROR)   then  
              begin  
                  sDefaultPrinter   :=   DefaultPrinterDevice;  
                  el.Reset;  
                  while   el.Next(1,   pidl2,   c)   =   NOERROR   do  
                  begin  
                      if   PidlToStr(sf2,   pidl2)   =   sDefaultPrinter   then  
                          ExecuteContextMenuCommand(Application.Handle,   sf2,   pidl2);  
                      malloc.Free(pidl2);  
                  end;  
              end;  
          finally  
              malloc.Free(pidl1);  
          end;  
  end;

没有研究过打印机的东西,手头有些资料,你看能不能用上用API直接打印    
  uses   CommDlg;    
   
  {$ IFNDEF   WIN32}    
  const   MAX_PATH   =   144;    
  {$ ENDIF}    
   
  procedure   TForm1.Button1Click(Sender:   TObject);    
  var    
  Pd   :   TPrintDlg;    
  DocInfo:   TDocInfo;    
  begin    
  FillChar(Pd,   sizeof(Pd),   #0);    
  Pd.lStructSize   :=   sizeof(Pd);    
  Pd.hWndOwner   :=   Form1.Handle;    
  Pd.Flags   :=   PD_RETURNDC;    
  if   PrintDlg(pd)   then   begin    
  FillChar(DocInfo,   sizeof(DocInfo),   #0);    
  DocInfo.cbSize   :=   SizeOf(DocInfo);    
  GetMem(DocInfo.lpszDocName,   32);    
  GetMem(DocInfo.lpszOutput,   MAX_PATH);    
  lStrCpy(DocInfo.lpszDocName,   'My   Document');    
  {Add   this   line   to   print   to   a   file   }    
  lStrCpy(DocInfo.lpszOutput,   'C:\Download\Test.doc');    
  StartDoc(Pd.hDc,   DocInfo);    
  StartPage(Pd.hDc);    
  TextOut(Pd.hDc,   100,   100,   'Page   1',   6);    
  EndPage(Pd.hDc);    
  StartPage(Pd.hDc);    
  TextOut(Pd.hDc,   100,   100,   'Page   2',   6);    
  EndPage(Pd.hDc);    
  EndDoc(Pd.hDc);    
  FreeMem(DocInfo.lpszDocName,   32);    
  FreeMem(DocInfo.lpszOutput,   MAX_PATH);    
  end;    
  end;     
 

标签集:TAGS:
回复Comments() 点击Count()

回复Comments

{commentauthor}
{commentauthor}
{commenttime}
{commentnum}
{commentcontent}
作者:
{commentrecontent}