技术积累

明日复明日,明日何其多,我生待明日,万事成蹉跎。
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

C# 逐行驱动打印

Posted on 2005-09-08 22:15  追风逐云.NET  阅读(4117)  评论(3编辑  收藏  举报

windows打印以page方式驱动打印机,行方式驱动需调用API或用种变通的方式。

方法一

简单的写到一个文件里然后

System.Diagnostics.Process.Start("cmd"," /c copy d:\1.txt  prn")

输出重定向简单易行打个receipt啥的足够用,就是感觉很业余,呵呵。

方法二
这个就要用几个API 了

Class  RawPrinterHelper

using System;
using System.IO; 
using System.Drawing.Printing; 
using System.Runtime.InteropServices; 


public class RawPrinterHelper 

    [StructLayout(LayoutKind.Sequential, CharSet
=CharSet.Unicode)] 
        
public struct DOCINFOW 
    

        [MarshalAs(UnmanagedType.LPWStr)] 
        
public string pDocName; 
        [MarshalAs(UnmanagedType.LPWStr)] 
        
public string pOutputFile; 
        [MarshalAs(UnmanagedType.LPWStr)] 
        
public string pDataType; 
    }
 

    [DllImport(
"winspool.Drv", EntryPoint="OpenPrinterW", CallingConvention=CallingConvention.StdCall, CharSet=CharSet.Unicode, SetLastError=true, ExactSpelling=true)]
    
public static extern bool OpenPrinter(string src, ref IntPtr hPrinter, long pd);
 


    [DllImport(
"winspool.Drv", CallingConvention=CallingConvention.StdCall, CharSet=CharSet.Unicode, SetLastError=true, ExactSpelling=true)]
    
public static extern bool ClosePrinter(IntPtr hPrinter);
 


    [DllImport(
"winspool.Drv", EntryPoint="StartDocPrinterW", CallingConvention=CallingConvention.StdCall, CharSet=CharSet.Unicode, SetLastError=true, ExactSpelling=true)]
    
public static extern bool StartDocPrinter(IntPtr hPrinter, int level, ref RawPrinterHelper.DOCINFOW pDI);
 


    [DllImport(
"winspool.Drv", EntryPoint="EndDocPrinter", SetLastError=true, CharSet=CharSet.Unicode, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)] 
    
public static extern bool EndDocPrinter(IntPtr hPrinter); 
    

    [DllImport(
"winspool.Drv", EntryPoint="StartPagePrinter", SetLastError=true, CharSet=CharSet.Unicode, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)] 
    
public static extern bool StartPagePrinter(IntPtr hPrinter) ;
    

    [DllImport(
"winspool.Drv", EntryPoint="EndPagePrinter", SetLastError=true, CharSet=CharSet.Unicode, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)] 
    
public static extern bool EndPagePrinter(IntPtr hPrinter) ;
    

    [DllImport(
"winspool.Drv", CallingConvention=CallingConvention.StdCall, CharSet=CharSet.Unicode, SetLastError=true, ExactSpelling=true)]
    
public static extern bool WritePrinter(IntPtr hPrinter, IntPtr pBytes, int dwCount, ref int dwWritten);
 


    
public static bool SendBytesToPrinter(string szPrinterName, IntPtr pBytes, Int32 dwCount) 
    

        IntPtr hPrinter 
=  System.IntPtr.Zero; 
        Int32 dwError; 
        DOCINFOW di 
= new DOCINFOW(); 
        Int32 dwWritten 
= 0
        
bool bSuccess; 
        di.pDocName 
= "My Document"
        di.pDataType 
= "RAW"
        bSuccess 
= false
        
if (OpenPrinter(szPrinterName,ref hPrinter, 0)) 
        

            
if (StartDocPrinter(hPrinter, 1,ref di)) 
            

                
if (StartPagePrinter(hPrinter)) 
                

                    bSuccess 
= WritePrinter(hPrinter, pBytes, dwCount, ref dwWritten); 
                    EndPagePrinter(hPrinter); 
                }
 
                EndDocPrinter(hPrinter); 
            }
 
            ClosePrinter(hPrinter); 
        }
 
        
if (bSuccess == false
        

            dwError 
= Marshal.GetLastWin32Error(); 
        }
 
        
return bSuccess; 

    }
 


    
public static bool SendFileToPrinter(string szPrinterName, string szFileName) 
    

        FileStream stream1 
= new FileStream(szFileName, FileMode.Open);
        BinaryReader reader1 
= new BinaryReader(stream1);
        
byte[] buffer1 = new byte[((int) stream1.Length) + 1];
        buffer1 
= reader1.ReadBytes((int) stream1.Length);
        IntPtr ptr1 
= Marshal.AllocCoTaskMem((int) stream1.Length);
        Marshal.Copy(buffer1, 
0, ptr1, (int) stream1.Length);
        
bool flag1 = RawPrinterHelper.SendBytesToPrinter(szPrinterName, ptr1, (int) stream1.Length);
        Marshal.FreeCoTaskMem(ptr1);
        
return flag1;

    }
 

    
public static void SendStringToPrinter(string szPrinterName, string szString) 
    

        IntPtr pBytes; 
        Int32 dwCount; 
        dwCount 
= szString.Length; 
        pBytes 
= Marshal.StringToCoTaskMemAnsi(szString); 
        SendBytesToPrinter(szPrinterName, pBytes, dwCount); 
        Marshal.FreeCoTaskMem(pBytes); 
    }
 
}



调用


    sPrintStr   
= " test"

    PrintDialog pd 
= new PrintDialog(); 
    pd.PrinterSettings 
= new PrinterSettings(); 
    
//if (pd.ShowDialog(this) > DialogResult.None)
    
//{
    RawPrinterHelper.SendStringToPrinter(pd.PrinterSettings.PrinterName, sPrintStr); 
    
//}

 

有段以前VB的懒的改了找了段VB.net  http://support.microsoft.com/default.aspx?scid=KB;EN-US;322090 的翻过来,结果搞了一个多小时才调通还不如自己写呢。
原代码语法翻译工具 VB.Net  To C# 编译时候会遇到n多默认名空间、类型转换、修饰符、返回值、初始化、方法的()等问题,SendFileToPrinter是编译后用Reflector反编译回来的也有些莫名其妙的问题。
我语法翻译了一份,反编译一份对照这改才算调试通过了。
VB.net的代码还是编译了再 DllImport方便些。