打印机用的是卷纸,有驱动
问题1、使用驱动是否就不能一行一行打印了(像打印小票那样)?
问题2、用AssignFile并口可绕过驱动直接用打印机命令打印,但如何读打印机状态?
问题3、用AssignFile并口打印,用api+驱动读打印机状态,可行否?小弟刚加入,初学,分有多少加多少,大家别闲少哈,谢谢

解决方案 »

  1.   

    我没用过DEPHI,但我知道用API是可以一行一行打印的。也是通过驱动打印的。我是用c写的,用到以下API函数,可供参考
    OpenPrinter
    GetPrinter
    StartDocPrinter
    WritePrinter
    EndDocPrinter
    ClosePrinter
      

  2.   

    方法一:利用Delphi 的TPrinter 类  TPrinter 类是Delphi 对Windows 打印处理系统的封装,它能够帮助程序员在开发打印程序时尽可能地减少工作量。在程序中使用TPrinter,只要在单元的Use 子句后面添加Printers 即可。当前打印机的DevMode 结构的句柄可以通过调用Tprinter 类中的GetPrinter 方法来获取。当程序获得DevMode 结构的句柄后,就调用GlobalLock 函数来得到指向该结构的指针,随后可对结构中的某些成员进行修改。下面就举一个例子来说明这一问题:假设当前打印机的默认纸张尺寸是A3 纸,现在要打印长度为114mm、宽度为190mm 的纸张。为了简单起见,我们只在Form1 上放置一个Button1 按钮,增加一个OnClick 事件,在Use 子句后添加Printers。程序的代码如下:Procedure TForm1.Button1Click(Sender: TObject);
    var
     Device : array[0..cchDeviceName -1] of Char;
     Driver : array[0..(MAX_PATH -1)] of Char;
     Port : array[0..32]of Char;
     hDMode : THandle;
     pDMode : PDevMode;
    begin
      Printer.GetPrinter(Device,Driver,Port,hDMode);
    // 获取打印机DevMode 结构的句柄值,
     存放在hDMode 中
      if hDMode < > 0 then begin
        pDMode := GlobalLock(hDMode); 
    // 获取指向打印机DevMode 结构的// 指针
        if pDMode < > nil then begin
         pDMode^.dmPaperSize := 256; 
    // 如果要将当前打印机纸张变为自定义
    dmPaperSize 必须设置成256
       pDMode^.dmPaperLength := 1140;
       pDMode^.dmPaperWidth := 1900;
       pDMode^.dmFields := pDMode^.dmFields or 
    DM_PAPERSIZE;
     pDMode^.dmFields := 
      pDMode^.dmFields or DM_PAPERLENGTH;
     pDMode^.dmFields := 
      pDMode^.dmFields or DM_PAPERWIDTH;
       { 以上三条语句是对相应
        的dmFields 成员进行置位。}
       ResetDC(Printer.Handle,pDMode^); 
    // 设置打印机设备环境句柄的值
       GlobalUnlock(hDMode);
       end;
      end;
    { 下面的代码是为了测试打印机是否
     按190 *114 纸张大小来打印}
      with Printer do begin
       BeginDoc;
       Canvas.TextOut(10,10,'Hello, My Friend!');
       EndDoc;
      end;
    end;
    方法二:利用有关打印的Windows API 函数  解决问题的思路和第一种方法类似,首先要获取当前打印机的DevMode 结构的指针,然后再对该结构进行修改,从而修改打印机纸张大小。要完成上述功能,就得调用DocumentProperties 函数。利用该函数程序就可以获取并修改与当前打印机相关的DevMode 结构中的成员。DocumentProperties 函数申明如下:LONG DocumentProperties
    (
      HWND    hWnd, 
      HANDLE   hPrinter,    
      LPTSTR   pDeviceName,  
      PDEVMODE pDevModeOutput, 
      PDEVMODE pDevModeInput,  
      DWORD   fMode 
    );
      六个参数中只有pDevModeOutput 是输出变量,其余五个参数必须由程序给出具体值。其中,hWnd 表征当前窗口的句柄值;hPrinter 表示当前打印机的句柄;pDeviceName 是对打印机设备的描述;pDevModeOutput 是指向句柄值为hPrinter 的打印机DevMode 结构的指针;pDevModeInput 是指向一个修改后的DevMode 结构的指针,该结构有待于被句柄值为hPrinter 的打印机接受;fMode 定义了该函数的具体功能,如果取值DM_IN_BUFFER 那么表示打印机接受由参数pDevModeInput 表示的由程序修改了的DevMode 值,如果取值DM_OUT_BUFFER 那么程序可以通过参数pDevModeOutput 来获取打印机的DevMode 值,如果fMode 为零,则函数返回的值表示结构DevMode 所需的字节数。承接上述例子,现在将190 *114 大小的纸张设成A4 纸。再往Form1 上放置按钮Button2,增加OnClick 事件,在Use 子句后面添加WinSpool。代码如下:Procedure TForm1.Button2Click(Sender: TObject);
    var
      PrnHd : THandle;
      PrnInfo : PPrinterInfo1;
      pcbNeeded : DWORD;
      PDevModeBytes : DWORD;
      DevMode: PDeviceMode;
      PrnHdc : HDC;
      DocInfo : PDocInfo;
    begin
      OpenPrinter('Epson LQ -1600K',PrnHd,nil); 
      // 获得打印机句柄PrnHd
      GetMem(PrnInfo,1024);
      GetPrinter(PrnHd,1,PrnInfo,1024,@pcbNeeded);
      PDevModeBytes:= DocumentProperties
    ( Handle,PrnHd,prninfo^.
     pDescription,DevMode^,DevMode^,0 );
    { 获取DevMode 结构所需的字节数}
      GetMem(DevMode,PDevModeBytes); 
    // 给结构DevMode 分配空间
      DocumentProperties( Handle,PrnHd,PrnInfo^.p
     Description,DevMode^,DevMode^,DM_OUT_BUFFER );
    // 获取打印机的DevMode 结构
      With DevMode^ do begin
       dmPaperSize := DMPAPER_A4   ;
    // 将纸张设置成A4 纸
       dmFields := dmFields or DM_PAPERSIZE;
      end;
      DocumentProperties( Handle,PrnHd,PrnInfo^.p
    Description,DevMode^,DevMode^,
    DM_OUT_BUFFER or DM_IN_BUFFER);
    // 修改DevMode 结构。
     { 下面的代码是为了测试打印机
      是否按A4 纸大小来打印 }
      PrnHdc := CreateDC
    ( nil, 'Epson LQ -1600K',nil,DevMode );
      GetMem( DocInfo, 100 );
      With DocInfo^ do begin
       cbSize := sizeof(DocInfo);
       lpszDocName := nil;
       lpszOutput := nil;
       lpszDatatype := nil;
       fwType := DI_APPBANDING;
      end;
      StartDoc( PrnHdc, DocInfo^);
      StartPage(PrnHdc);
      TextOut( PrnHdc, 10, 10, 'Hello My Friend!',17);
      EndPage(PrnHdc);
      EndDoc(PrnHdc);
      DeleteDC(PrnHdc);
      FreeMem(DocInfo);
      FreeMem(PrnInfo);
      FreeMem(DevMode);
    end;
      

  3.   

    谢谢两位顶我的帖子!
    一楼的,用api打印时不用设置纸张大小么?按二楼的例子还是要设置纸张大小呀!偶迷糊中~~~~
    我正考虑用AssignFile+winio的方式,或干脆直接用winio,正在调试中,有什么好建议?