分享

C# 实现虚拟打印机 HP Color LaserJet 4500 (1)

 gogo8848 2015-08-06
分类: 数据 .NET 图形 2010-05-11 17:09 5594人阅读 评论(12) 收藏 举报

C# 实现虚拟打印机 HP Color LaserJet 4500  1

 

无聊了研究了下PCLHPGL两种语言。如果要实现虚拟打印机只使用.NET来做,驱动是最大的问题。其实我们可以使用已经写好的打印机驱动来实现。只是让驱动最终生成的打印语言输出到我们想要的位置。并且我们对打印语言进行模拟显示就可以。经过几天的研究发现HP Color LaserJet 4500 打印出的图形为PCLHPGL的混合体。那就写个控制HP Color LaserJet 4500的程序进行控制并且把打印出的打印语言输出到我们想要的位置。

 

首先 先给系统添加打印机 HP Color LaserJet 4500

 

 

 

其他的设置不用管。用程序来控制把,免得配置复杂以后我自己都忘了怎么配置的。

思路  先给打印机更换端口 使用写注册表 把临时目录放做为打印端口 然后设置打印后保留文档 通过API  EnumJobs 获取打印任务 重新执行打印后获取临时文件 ,这里临时文件就是我们需要的PCL/HPGL文件( ImagePRN 这个类 我暂时不贴出来) 因为包含两种打印语言所以这个东西的类我还的找个时间再整理下,到目前为止就10来个类了贴出来太累了。等整理后、成一个类后我会帖出来。

 效果图

 

 

不说了 先看代码把

测试使用代码

 

[c-sharp] view plaincopy
  1. using System;  
  2. using System.Collections;  
  3. using System.Collections.Generic;  
  4. using System.ComponentModel;  
  5. using System.Data;  
  6. using System.Drawing;  
  7. using System.Drawing.Imaging;  
  8. using System.Text;  
  9. using System.Windows.Forms;  
  10.   
  11. using Zgke.Code;  
  12.   
  13.   
  14. namespace WindowsApplication1  
  15. {  
  16.       
  17.   
  18.     public partial class Form1 : Form  
  19.     {  
  20.          
  21.         public Form1()  
  22.         {  
  23.             InitializeComponent();  
  24.             
  25.         }  
  26.   
  27.         /// <summary>  
  28.         /// 最终保存PCL文件的路径  
  29.         /// </summary>  
  30.         private string p_FileDir = @"D:/temp/PCL/";  
  31.     
  32.         /// <summary>  
  33.         /// 打印控制器   
  34.         /// </summary>  
  35.         private PrintControlSet m_SetControl;  
  36.   
  37.         /// <summary>  
  38.         /// PCL文件里的文档  
  39.         /// </summary>  
  40.         private IList<Image> m_PrintImageList;  
  41.   
  42.         private void Form1_Load(object sender, EventArgs e)  
  43.         {  
  44.             string[] _Filelist = System.IO.Directory.GetFiles(p_FileDir, "*.PCL");  
  45.             for (int i = 0; i != _Filelist.Length; i++)  
  46.             {  
  47.                 listBox1.Items.Add(_Filelist[i]);  
  48.             }  
  49.   
  50.             m_SetControl = new PrintControlSet("Zgke PrintOK", @"C:/1.PRN");  
  51.             m_SetControl.PrintJobLoad += new PrintControlSet.PrintJobFile(_SetControl_PrintJobLoad);  
  52.             m_SetControl.SaveFileOver += new PrintControlSet.SaveOver(_SetControl_SaveFileOver);  
  53.             m_SetControl.StarMonitor();           
  54.         }  
  55.   
  56.         /// <summary>  
  57.         /// 文件复制完成后触发  
  58.         /// </summary>  
  59.         /// <param name="p_FileName"></param>  
  60.         void _SetControl_SaveFileOver(string p_FileName)  
  61.         {  
  62.             this.Invoke((MethodInvoker)delegate { listBox1.Items.Add(p_FileName); });   
  63.         }   
  64.   
  65.         /// <summary>  
  66.         /// 需要处理时触发  这里可以根据需要写到数据库里。 我只用了日期 并没有使用档名 这个名字可能文件不能创建  
  67.         /// </summary>   
  68.         /// <param name="p_Document"></param>  
  69.         /// <param name="p_PrintDateTime"></param>  
  70.         /// <param name="p_MachineName"></param>  
  71.         /// <param name="p_UserName"></param>  
  72.         /// <param name="p_PageCount"></param>  
  73.         /// <param name="p_PrintOK"></param>  
  74.         /// <param name="p_SaveFileName"></param>  
  75.         void _SetControl_PrintJobLoad(string p_Document, DateTime p_PrintDateTime, string p_MachineName, string p_UserName, int p_PageCount, out bool p_PrintOK, out string p_SaveFileName)  
  76.         {  
  77.             p_PrintOK = true;  
  78.             p_SaveFileName = p_FileDir +p_PrintDateTime.ToString("yyyyMMddHHmmssffff")+".PCL";             
  79.         }  
  80.   
  81.         private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)  
  82.         {  
  83.             pictureBox1.Image = m_PrintImageList[comboBox1.SelectedIndex];  
  84.         }  
  85.   
  86.         private void listBox1_DoubleClick(object sender, EventArgs e)  
  87.         {              
  88.             if (listBox1.SelectedItem == nullreturn;  
  89.             comboBox1.Items.Clear();  
  90.             ImagePRN _HPGL = new ImagePRN(listBox1.SelectedItem.ToString());  
  91.             m_PrintImageList = _HPGL.PrintBitmap;  
  92.             for (int i = 0; i != m_PrintImageList.Count; i++)  
  93.             {  
  94.                 comboBox1.Items.Add(i.ToString());  
  95.             }  
  96.             if (m_PrintImageList.Count != 0) comboBox1.SelectedIndex = 0;   
  97.         }  
  98.   
  99.     
  100.        
  101.     }  
  102. }  

 

下面是打印控制的类

[c-sharp] view plaincopy
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Text;  
  4. using System.Drawing.Printing;  
  5. using System.Threading;  
  6. using System.Runtime.InteropServices;  
  7.   
  8.   
  9.   
  10. namespace Zgke.Code  
  11. {  
  12.     /// <summary>  
  13.     /// zgke@sina.com  
  14.     /// qq:116149  
  15.     /// 虚拟打印机控制器  
  16.     /// </summary>  
  17.     public class PrintControlSet  
  18.     {  
  19.         // <summary>  
  20.         /// 保存文件  
  21.         /// </summary>  
  22.         /// <param name="p_Document">文档名称</param>         
  23.         /// <param name="p_PrintDateTime">打印日期</param>  
  24.         /// <param name="p_MachineName">计算机名</param>  
  25.         /// <param name="p_UserName">用户名</param>  
  26.         /// <param name="p_PageCount">用户名</param>  
  27.         /// <param name="m_PrintOK">是否处理完成 如果为false 那下次监控还会触发这个</param>  
  28.         /// <param name="p_SaveFileName">保存PRN文件到指定的位置</param>  
  29.         public delegate void PrintJobFile(string p_Document,DateTime p_PrintDateTime,string p_MachineName,string p_UserName,int p_PageCount, out bool m_PrintOK,out string p_SaveFileName);  
  30.         /// <summary>  
  31.         /// 获取打印事件  
  32.         /// </summary>  
  33.         public event PrintJobFile PrintJobLoad;  
  34.   
  35.         /// <summary>  
  36.         /// 保存完成  
  37.         /// </summary>  
  38.         /// <param name="p_FileName">复制完成后的文件位置</param>         
  39.         public delegate void SaveOver(string p_FileName);  
  40.         /// <summary>  
  41.         /// 保存完成  
  42.         /// </summary>  
  43.         public event SaveOver SaveFileOver;  
  44.   
  45.         /// <summary>  
  46.         /// 监视线程  
  47.         /// </summary>  
  48.         private System.Timers.Timer m_Timer;  
  49.   
  50.         /// <summary>  
  51.         /// 设置时间间隔  
  52.         /// </summary>  
  53.         public double Interval { get { return m_Timer.Interval; } set { m_Timer.Interval = value; } }    
  54.   
  55.         /// <summary>  
  56.         /// 打印器名称   
  57.         /// </summary>  
  58.         private string m_PrintName = "";  
  59.   
  60.         /// <summary>  
  61.         /// 打印临时目录  
  62.         /// </summary>  
  63.         private string m_TempFile = "";  
  64.   
  65.         /// <summary>  
  66.         /// 打印设置器  先去安装 HP Color LaserJet 4500 打印机   
  67.         /// </summary>  
  68.         /// <param name="p_PrintName"></param>  
  69.         public PrintControlSet(string p_PrintName,string p_TempFile)  
  70.         {  
  71.             if (p_PrintName.Length == 0) throw new Exception("必须指定打印机名称!");  
  72.             m_PrintName = p_PrintName;  
  73.             m_TempFile = p_TempFile;  
  74.             m_Timer = new System.Timers.Timer();  
  75.             m_Timer.Interval = 1000;  
  76.             m_Timer.Elapsed += new System.Timers.ElapsedEventHandler(m_Timer_Elapsed);  
  77.             Microsoft.Win32.RegistryKey _Regisity = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE/Microsoft/Windows NT/CurrentVersion/Print/Printers");  
  78.   
  79.             string[] _PrintName =_Regisity.GetSubKeyNames();  
  80.             for (int i = 0; i != _PrintName.Length; i++)  
  81.             {  
  82.                 if (_PrintName[i] == m_PrintName)  
  83.                 {  
  84.                     AddPort();  
  85.                     SetPrintAttrib();  
  86.                     RestSpooler();  
  87.                     return;  
  88.                 }  
  89.             }  
  90.             throw new Exception("无法找到对应的打印机!");              
  91.         }  
  92.   
  93.         /// <summary>  
  94.         /// 监控打印缓冲区  
  95.         /// </summary>  
  96.         /// <param name="sender"></param>  
  97.         /// <param name="e"></param>  
  98.         void m_Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)  
  99.         {  
  100.             m_Timer.Stop();  
  101.             IntPtr _PrintIntPtr = IntPtr.Zero;  
  102.             IntPtr _PrintDefault = IntPtr.Zero;  
  103.   
  104.             bool A = Win32API.OpenPrinter("Zgke PrintOK"out  _PrintIntPtr, _PrintDefault);  
  105.   
  106.             uint _dwNeeded;  
  107.             uint _dwReturned;  
  108.   
  109.             for (int i = 0; i != 65535; i++)  
  110.             {  
  111.                 IntPtr _JobIntPtr = Marshal.AllocHGlobal(1000);  
  112.                 Win32API.EnumJobs(_PrintIntPtr, (uint)i, 1, 1, _JobIntPtr, 1000, out _dwNeeded, out _dwReturned);  
  113.                 if (_dwReturned == 0)  
  114.                 {  
  115.                     Marshal.FreeHGlobal(_JobIntPtr);  
  116.                     break;  
  117.                 }  
  118.   
  119.                 JOB_INFO_1 _JobInfo = (JOB_INFO_1)Marshal.PtrToStructure(_JobIntPtr, typeof(JOB_INFO_1));  
  120.   
  121.                 if (_JobInfo.Status != 128)  
  122.                 {  
  123.                     Marshal.FreeHGlobal(_JobIntPtr);  
  124.                     continue;  
  125.                 }  
  126.                 DateTime _PrintTime = new DateTime(_JobInfo.Submitted.wYear, _JobInfo.Submitted.wMonth, _JobInfo.Submitted.wDay, _JobInfo.Submitted.wHour, _JobInfo.Submitted.wMinute, _JobInfo.Submitted.wSecond, _JobInfo.Submitted.wMilliseconds);  
  127.                 if (PrintJobLoad != null)  
  128.                 {  
  129.                     bool _PrintOK = false;  
  130.                     string _SaveFile = "";  
  131.                     PrintJobLoad(_JobInfo.pDocument, _PrintTime, _JobInfo.pMachineName, _JobInfo.pUserName, _JobInfo.TotalPages, out _PrintOK, out _SaveFile);  
  132.                     if (_PrintOK)  
  133.                     {  
  134.                         int _State = Win32API.SetJob(_PrintIntPtr, _JobInfo.JobId, 0, IntPtr.Zero, JOB_CONTROL.JOB_CONTROL_RESTART);  
  135.                         WaitForPrintOver(_PrintIntPtr, i);  
  136.                         if (_SaveFile.Length != 0)System.IO.File.Copy(m_TempFile, _SaveFile, true);                         
  137.                         _State = Win32API.SetJob(_PrintIntPtr, _JobInfo.JobId, 0, IntPtr.Zero, JOB_CONTROL.JOB_CONTROL_CANCEL);  
  138.                         if (SaveFileOver != null) SaveFileOver(_SaveFile);  
  139.                     }  
  140.                     Marshal.FreeHGlobal(_JobIntPtr);  
  141.                 }                 
  142.             }  
  143.             Win32API.ClosePrinter(_PrintIntPtr);  
  144.             m_Timer.Start();  
  145.         }  
  146.   
  147.         /// <summary>  
  148.         /// 等待打印完成  
  149.         /// </summary>  
  150.         /// <param name="p_JobId">任务ID</param>  
  151.         public void WaitForPrintOver(IntPtr p_PrintIntPtr, int p_JobId)  
  152.         {  
  153.             while (true)  
  154.             {  
  155.                 uint _dwNeeded;  
  156.                 uint _dwReturned;  
  157.                 IntPtr _JobIntPtr = Marshal.AllocHGlobal(1000);  
  158.                 Win32API.EnumJobs(p_PrintIntPtr, (uint)p_JobId, 1, 1, _JobIntPtr, 1000, out _dwNeeded, out _dwReturned);  
  159.                 if (_dwReturned != 0)  
  160.                 {  
  161.                     JOB_INFO_1 _JobInfo = (JOB_INFO_1)Marshal.PtrToStructure(_JobIntPtr, typeof(JOB_INFO_1));     
  162.                     if (_JobInfo.Status == 128) return;  
  163.                 }  
  164.                 System.Windows.Forms.Application.DoEvents();  
  165.                 Marshal.FreeHGlobal(_JobIntPtr);  
  166.             }  
  167.         }     
  168.   
  169.         /// <summary>  
  170.         /// 添加一个端口  
  171.         /// </summary>  
  172.         private void AddPort()  
  173.         {  
  174.             Microsoft.Win32.RegistryKey _Regisity = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE/Microsoft/Windows NT/CurrentVersion/Ports",true);  
  175.             string[] _ValueName = _Regisity.GetValueNames();  
  176.             for (int i = 0; i != _ValueName.Length; i++)  
  177.             {  
  178.                 if (_ValueName[i] == m_TempFile) return;  
  179.             }  
  180.             _Regisity.SetValue(m_TempFile, "", Microsoft.Win32.RegistryValueKind.String);  
  181.         }  
  182.   
  183.         /// <summary>  
  184.         /// 设置打印机属性  
  185.         /// </summary>  
  186.         private void SetPrintAttrib()  
  187.         {  
  188.             Microsoft.Win32.RegistryKey _Regisity = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE/Microsoft/Windows NT/CurrentVersion/Print/Printers/"+m_PrintName,true);  
  189.             int _Attrib = (int)_Regisity.GetValue("Attributes");  
  190.             _Attrib |= 0x100;  
  191.             _Regisity.SetValue("Attributes", _Attrib);  
  192.             _Regisity.SetValue("Port", m_TempFile);  
  193.         }  
  194.   
  195.         /// <summary>  
  196.         /// 重新启动服务  
  197.         /// </summary>  
  198.         private void RestSpooler()  
  199.         {  
  200.             System.ServiceProcess.ServiceController[] _Spooler = System.ServiceProcess.ServiceController.GetServices();  
  201.             for (int i = 0; i != _Spooler.Length; i++)  
  202.             {   
  203.                 if (_Spooler[i].ServiceName == "Spooler")  
  204.                 {  
  205.                     if (_Spooler[i].Status != System.ServiceProcess.ServiceControllerStatus.Stopped)  
  206.                     {  
  207.                         _Spooler[i].Stop();  
  208.                         _Spooler[i].WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Stopped);  
  209.                     }  
  210.                     _Spooler[i].Start();  
  211.                     _Spooler[i].WaitForStatus(System.ServiceProcess.ServiceControllerStatus.Running);  
  212.                 }  
  213.             }  
  214.               
  215.         }  
  216.   
  217.         /// <summary>  
  218.         /// 开始监控  
  219.         /// </summary>  
  220.         public void StarMonitor()  
  221.         {  
  222.             m_Timer.Start();  
  223.         }  
  224.   
  225.         /// <summary>  
  226.         /// 停止监控  
  227.         /// </summary>  
  228.         public void StopMonitor()  
  229.         {  
  230.             m_Timer.Stop();  
  231.         }  
  232.          
  233.     }  
  234.   
  235.   
  236.     public class Win32API  
  237.     {  
  238.   
  239.         [DllImport("winspool.drv", EntryPoint = "EnumJobsA")]  
  240.         public static extern bool EnumJobs(IntPtr hPrinter, uint FirstJob, uint NoJobs, uint Level, IntPtr pJob, uint cdBuf, out uint pcbNeeded, out uint pcReturned);  
  241.   
  242.         [DllImport("winspool.drv", EntryPoint = "SetJob")]  
  243.         public static extern int SetJob(IntPtr hPrinter, int JobId, int Level, IntPtr pJob, JOB_CONTROL Command);  
  244.   
  245.   
  246.         [DllImport("winspool.drv", CharSet = CharSet.Auto)]  
  247.         public static extern bool OpenPrinter(string pPrinterName, out IntPtr phPrinter, IntPtr pDefault);  
  248.   
  249.         [DllImport("winspool.drv", CharSet = CharSet.Auto)]  
  250.         public static extern bool ClosePrinter(IntPtr ptrPrinter);         
  251.     }  
  252.   
  253.     public enum JOB_CONTROL  
  254.     {  
  255.         JOB_CONTROL_PAUSE = 1,  
  256.         JOB_CONTROL_RESUME = 2,  
  257.         JOB_CONTROL_CANCEL = 3,  
  258.         JOB_CONTROL_RESTART = 4  
  259.     }  
  260.   
  261.     [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]  
  262.     public struct JOB_INFO_1  
  263.     {  
  264.         public int JobId;  
  265.         [MarshalAs(UnmanagedType.LPStr)]  
  266.         public string pPrinterName;  
  267.         [MarshalAs(UnmanagedType.LPStr)]  
  268.         public string pMachineName;  
  269.         [MarshalAs(UnmanagedType.LPStr)]  
  270.         public string pUserName;  
  271.         [MarshalAs(UnmanagedType.LPStr)]  
  272.         public string pDocument;  
  273.         [MarshalAs(UnmanagedType.LPStr)]  
  274.         public string pDatatype;  
  275.         [MarshalAs(UnmanagedType.LPStr)]  
  276.         public string pStatus;  
  277.         public int Status;  
  278.         public int Priority;  
  279.         public int Position;  
  280.         public int TotalPages;  
  281.         public int PagesPrinted;  
  282.         public SYSTEMTIME Submitted;  
  283.     }  
  284.   
  285.     [StructLayout(LayoutKind.Sequential)]  
  286.     public struct SYSTEMTIME  
  287.     {  
  288.         public short wYear;  
  289.         public short wMonth;  
  290.         public short wDayOfWeek;  
  291.         public short wDay;  
  292.         public short wHour;  
  293.         public short wMinute;  
  294.         public short wSecond;  
  295.         public short wMilliseconds;  
  296.     }  
  297.   
  298. }  

 

 下一篇 我会把PCL/HPGL的类贴出来。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多