遇到头痛的问题,大家帮帮忙~

解决方案 »

  1.   

    给你个获取打印机状态的文章吧:
    var 
    pinfo: pPRINTERINFO2;
      pprt,a: Cardinal;
      b:PDWORD;
    begin
      b:=allocmem(256);
      pinfo:=AllocMem(1000);
      if OpenPrinter('HP DJ 200',pprt,nil) then
      begin
        a:=1000;
        if getprinter(pprt,2,pinfo,a,b) then
          showmessage(pinfo.pPrinterName+' ststus:'+inttostr(pinfo.Status));
      ClosePrinter(pprt);
      end;
      
      freemem(b);
      freemem(pinfo);
    end;PRINTER_INFO_2.Status :
     Windows NT: 
       PRINTER_STATUS_PAUSED
       PRINTER_STATUS_PENDING_DELETION 
     Windows 95: 
       PRINTER_STATUS_BUSY
       PRINTER_STATUS_DOOR_OPEN
       PRINTER_STATUS_ERROR
       PRINTER_STATUS_INITIALIZING
       PRINTER_STATUS_IO_ACTIVE
       PRINTER_STATUS_MANUAL_FEED
       PRINTER_STATUS_NO_TONER
       PRINTER_STATUS_NOT_AVAILABLE
       PRINTER_STATUS_OFFLINE
       PRINTER_STATUS_OUT_OF_MEMORY
       PRINTER_STATUS_OUTPUT_BIN_FULL
       PRINTER_STATUS_PAGE_PUNT
       PRINTER_STATUS_PAPER_JAM
       PRINTER_STATUS_PAPER_OUT
       PRINTER_STATUS_PAPER_PROBLEM
       PRINTER_STATUS_PAUSED
       PRINTER_STATUS_PENDING_DELETION
       PRINTER_STATUS_PRINTING
       PRINTER_STATUS_PROCESSING
       PRINTER_STATUS_TONER_LOW
       PRINTER_STATUS_UNAVAILABLE
       PRINTER_STATUS_USER_INTERVENTION
       PRINTER_STATUS_WAITING
       PRINTER_STATUS_WARMING_UP 
    //////////////////////////////////////////////////////////////////
    unit PrinterStatus;interfaceuses
      Windows, Messages, WinProcs, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
    // TPrinterstatus
    // Komponente zum Abfragen des aktuellen Druckerportstatus
    // Programmiert 2000 von K. Otto
    // funktioniert unter Win 9x, jedoch nicht unter Win NT
    // ---------------------------------
    // Status: Freeware incl. Sourcecode
    // ---------------------------------
    // Diese Komponente beruht auf einem Beitrag von Robert Vivrette
    // f黵 "The unofficial Newsletter of Delphi Users"
    // http://www.undu.com/articles/990228a.htmltype
      TPrinterStatus = class(TComponent)
      private
        { Private-Deklarationen }
        fStatus : Byte;
        fLPT    : Integer;
        Function GetTimeOut : Boolean;
        Function GetIOError : Boolean;
        Function GetPrinterSelected : Boolean;
        Function GetOutOfPaper : Boolean;
        Function GetAcknowledgement : Boolean;
        Function GetPrinterBusy : Boolean;
      protected
        { Protected-Deklarationen }
      public
        { Public-Deklarationen }
        Procedure CheckPrinterStatus; // Liest den Druckerstatus der angegeben LPT-Schnittstelle
        Constructor Create(AOwner : TComponent); Override;
        Property TimeOut : Boolean Read GetTimeOut;
        Property IOError  : Boolean Read GetIOError;
        Property PrinterSelected : Boolean Read GetPrinterSelected;
        Property OutOfPaper : Boolean Read GetOutOfPaper;
        Property Acknowledgement : Boolean Read GetAcknowledgement;
        Property Busy : Boolean Read GetPrinterBusy;
      published
        { Published-Deklarationen }
        Property LPT : Integer Read fLPT Write fLPT;
      end;procedure Register;implementationprocedure Register;
    begin
      RegisterComponents('Eigene', [TPrinterStatus]);
    end;Function TPrinterStatus.GetTimeOut : Boolean;
    Begin
         Result:=(fStatus and $01)=$01;
    End;Function TPrinterStatus.GetIOError : Boolean;
    Begin
         Result:=(fStatus and $08)=$08;
    End;Function TPrinterStatus.GetPrinterSelected : Boolean;
    Begin
         Result:=(fStatus and $10)=$10;
    End;Function TPrinterStatus.GetOutOfPaper : Boolean;
    Begin
         Result:=(fStatus and $20)=$20;
    End;Function TPrinterStatus.GetAcknowledgement : Boolean;
    Begin
         Result:=(fStatus and $40)=$40;
    End;Function TPrinterStatus.GetPrinterBusy : Boolean;
    Begin
         Result:=not ((fStatus and $80)=$80);
    End;Procedure TPrinterStatus.CheckPrinterStatus;
    Var
       Status : Byte;
       CheckLPT : Word;
    Begin
         Status:=0;
         If (fLPT>=1) and (fLPT<=3) Then
         Begin
              CheckLPT:=fLPT-1;
              asm
                mov dx,CheckLPT;
                mov al,0;
                mov ah,2;
                int 17h;
                mov &Status, ah;
              End;
         End;
         fStatus:=Status;
    End;Constructor TPrinterStatus.Create(AOwner : TComponent);
    Begin
         Inherited Create(AOwner);
         fLPT:=1;
         fStatus:=0;
    End;end.
    //////////////////////////////////////////////////////
    用法: if not PrinterStatus1.PrinterReady(0) then  //0 = current printerport
      ShowMessage(PrinterStatus1.StatusMsg) else {print print print} ;unit PrinterStatus;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;type
      TPrinterStatus = class(TComponent)
      private
        { Private declarations }
        FPort : Word;
        FStatusStr : string;
      protected
        { Protected declarations }
      public
        { Public declarations }
        function PrinterReady(LPT: Word): boolean;
      published
        { Published declarations }
        property StatusMsg: string read FStatusStr;
      end;procedure Register;implementation
    uses Printers;procedure Register;
    begin
      RegisterComponents('Win95', [TPrinterStatus]);
    end;const
      PrnReady = $90;
      OffLine = $00;
      OffLine2 = $10;             {NEW LINE}
      PaperOut = $20;
      PaperOut2 = $30;            {NEW LINE}
      HookedButOff = $80;         {NEW LINE}
      NoConnect = $B0;            {MODIFIED LINE}  {NOCONNECT = $30 FOR SOME COMPUTERS BY STU}function TPrinterStatus.PrinterReady(LPT: Word): boolean;
    var
      ErrorCode, C : BYTE;
      code, x : integer;
      s : string;           function GetPrinterStatus (LPT: Word): Byte;
               {Pass 1 in LPT for LPT1}
               begin
                 asm
                   mov ah,2
                   mov dx,LPT
                   dec dx
                   int $17
                   mov @Result,ah
                 end;
               end;  {GetPrinterStatus}
    begin
     result := false;  //assume not FPort := LPT;
     if FPort = 0 then begin  {if no port specified then try to set port to current
    printer port}
       {printer name}
       s := Printer.Printers[Printer.PrinterIndex];
       if Pos('FPort',s) <> 0 then begin
         s := Copy(s, Pos('FPort',s) +3, 1);
         Val(s,x,code);
         if code <> 0 then FPort := 1 else FPort := x;
       end else FPort := 1;  {default to LPT1}
     end; {valid LPT is 1..4}
     if (FPort > 4) or (FPort < 1) then begin
       raise ERangeError.CreateFmt(
         'LPT%d is not within the valid range of %d..%d',
         [FPort, 1, 4]);
       exit;
     end;
     ErrorCode := GetPrinterStatus(FPort); ErrorCode := ErrorCode and $B0;       {NEW LINE} C := ERRORCODE shl 6;   {ALWAYS MEANS NOTHING CONNECTED} if C > 0 then ERRORCODE := $B0; {ELEMINATES NO LPT3 AND NOTHING CONNECTED} case ErrorCode of
      PrnReady            : begin FStatusStr := 'Printer Ready'; result := true;
    end;
      NoConnect           : FStatusStr := 'Printer not connected';
      Offline,OffLine2    : FStatusStr := 'Printer off line';     {Modified}
      PaperOut,PaperOut2  : FStatusStr := 'Printer out of paper'; {Modified}
      HookedButOff        : FStatusStr := 'Printer connected but turned off'; {New}
     else
      FStatusStr := 'Printer error code: ' + IntToStr(ErrorCode);
     end;end;
      

  2.   

    可用CREATEFILE以PRN为文件名生成一个文件,检测返回值,若成功则打印机可用,否则显示打印机故障。生成关于PRN的文件句柄后,可象普通文件一样向文件写入内容,比如WRITE,写完后关闭文件。
    //从并行端口读取打印机状态
    function GetPrinterStatus:byte;
    asm
      MOV DX,$379;
      IN AL,DX;
    end;
    //获取打印机是否出错
    function CheckPrinter:boolean;
    var
      temp:byte;
    begin
      temp:=GetPrinterStatus;
      Result:=not ( ((temp and $80)=0) //打印机忙
      or ((temp and $20)<>0)  //打印机缺纸
      or ((temp and $10)=0)    //打印机未联机
      or ((temp and $08)=0) ); //打印机出错;
    end;
      

  3.   

    为默认打印机创建一个快捷方式后,用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;
      

  4.   

    Printers是专门用来控制打印机的,可是在没有安装打印机时,却会提示I/O错误,所以必须有一个检测是否存在打印机的方法,我试过很多方法,可是I/O错误总是比我的判断早出现,所以采用以下的烂招来检测打印机。首先在uses增加Printers,再准备一个列表框ComboBox1,其属性Visible设为FALSE,然后在打印之前执行下列语句,那么就可以检测到是否存在打印机了:procedure TForm1.ButtonClick(Sender: Tobject);
    begin
    ComboBox1.Clear;
    ComboBox1.Items.Assign(Printer.Printers);
    if ComboBox1.Items.CommaText='' then
    Messagedlg('你需要安装打印机才能打印!',mtError,[mbOk],0);
    else
    Form1.Print; 
    end;
      

  5.   

    打印机状态检测    
        
    可用CREATEFILE以PRN为文件名生成一个文件,检测返回值,若成功则打印机可用,否则显示打印机故障。生成关于PRN的文件句柄后,可象普通文件一样向文件写入内容,比如WRITE,写完后关闭文件。//从并行端口读取打印机状态function GetPrinterStatus:byte;asmMOV DX,$379;IN AL,DX;end;//获取打印机是否出错function CheckPrinter:boolean;vartemp:byte;begintemp:=GetPrinterStatus;Result:=not ( ((temp and $80)=0) //打印机忙or ((temp and $20)<>0) //打印机缺纸or ((temp and $10)=0) //打印机未联机or ((temp and $08)=0) ); //打印机出错;end;