linux 打印作业状态监听,【VC++技术杂谈】打印技术之打印机状态监控

1.打印机虚脱机技术

在正式介绍如何对打印机状态进行实时监控之前,我们有必要先了解一下打印机虚脱机技术。

独占设备是指在一个程序(作业、用户)的整个运行期间独占设备,直到该程序(作业、用户)完成。系统的独占设备是有限的(比如,一台计算机只能够连接一台打印机),往往不能够满足多进程的要求,会引起大量进程由于等待某些独占设备而阻塞。另一方面,申请到独立设备的进程在其整个运行期间占有设备,利用率却非常低,造成独占设备长时间处于空闲状态。

为了解决这种矛盾,最常用的办法就是利用共享设备来模拟独占设备,从而提高系统效率和独占设备的利用率。该技术就是虚脱机技术(SPOOL:Simultaneous Peripaheral Operation On Line)。

打印机是典型的独占设备,引入虚脱机技术后,用户的打印请求传递给SPOOL系统,而不是真正的把打印机分配给用户。SPOOL系统先在磁盘上申请一个空闲区域,把需要打印的数据传输到里面,再把用户的打印请求挂到打印机队列上。如果打印机空闲,就会从打印机队列中取出一个打印请求,再从磁盘的对应区域取出数据,执行打印操作。由于磁盘是共享的,SPOOL系统可以随时响应打印请求并把数据缓存起来,以此实现独占设备模拟共享设备,从而提高系统效率和独占设备的利用率。

2.枚举当前打印机的打印任务

在Windows API中提供了如下一些打印相关枚举函数:

EnumForms();         //枚举当前打印机支持的所有页型

EnumJobs();           //枚举当前打印机的打印任务

EnumMonitors();         //枚举可用监视器

EnumPorts();          //枚举可用的打印端口

EnumPrinterDrivers();     //枚举打印机驱动程序

EnumPrinters();          //枚举打印机

EnumPrinterProcessors();   //枚举打印进程

我们要监控打印机状态,需要用到EnumJobs()函数,用来枚举当前打印机的打印任务。该函数的原型如下:

69c5a8ac3fa60e0848d784a6dd461da6.png

1 BOOL2 WINAPI3 EnumJobs(4 HANDLE hPrinter,5 DWORD FirstJob,6 DWORD NoJobs,7 DWORD Level,8 LPBYTE pJob,9 DWORD cbBuf,10 LPDWORD pcbNeeded,11 LPDWORD pcReturned12 );

69c5a8ac3fa60e0848d784a6dd461da6.png

其中,参数hPrinter表示打印机对象句柄;参数FirstJob表示作业列表中要枚举的第一个作业的索引(索引号从0开始);参数NoJobs表示要枚举的作业数量;参数Level表示级别(取值可以是1或2);参数pJob表示JOB_INFO_x结构的缓冲区(x由参数Level决定);参数cbBuf表示JOB_INFO_x结构的缓冲区大小;参数pcbNeeded用于保存请求的缓冲区长度;参数pcReturned则表示了载入缓冲区的结构数量。

3.具体编程实现

了解了EnumJobs()函数之后,我们就可以开始编写具体的代码了。

3.1获得打印机对象句柄

我们知道,EnumJobs()函数的第一个参数是打印机对象句柄hPrinter,所以在调用EnumJobs()函数之前,我们需要获得打印机对象句柄,这可以通过调用OpenPrinter()函数来实现。该函数原型为:

69c5a8ac3fa60e0848d784a6dd461da6.png

1 BOOL2 WINAPI3 OpenPrinter(4 LPSTR pPrinterName,5 LPHANDLE phPrinter,6 LPPRINTER_DEFAULTS pDefault7 );

69c5a8ac3fa60e0848d784a6dd461da6.png

其中,参数pPrinterName是打印机的名称;参数phPrinter就是我们想要得到的打印机对象句柄。

3.2获取打印状态

获取得到打印机对象句柄之后,我们便可以使用EnumJobs()函数来枚举打印任务,从而得到打印状态了。具体实现方法如下:

69c5a8ac3fa60e0848d784a6dd461da6.png

1 /*

2 * 函数功能 : 显示打印机状态

3 * 备 注 :

4 * 作 者 : 博客园 依旧淡然

5 */

6 voidCPrintDemoDlg::ShowPrinterStatus()

7 {

8 HANDLE printerHandle; //打印机设备句柄

9

10 //检测打开打印机设备是否成功

11 if(!OpenPrinter(m_strPrinterName.GetBuffer(0), &printerHandle, NULL))

12 return;

13

14 DWORD nByteNeeded;

15 DWORD nReturned;

16 DWORD nByteUsed;

17

18 //通过调用GetPrinter()函数得到作业数量

19 PRINTER_INFO_2* pPrinterInfo =NULL;

20 GetPrinter(printerHandle, 2, NULL, 0, &nByteNeeded);

21 pPrinterInfo = (PRINTER_INFO_2*)malloc(nByteNeeded);

22 GetPrinter(printerHandle, 2, (LPBYTE)pPrinterInfo, nByteNeeded, &nByteUsed);

23

24 //通过调用EnumJobs()函数枚举打印任务

25 JOB_INFO_2* pJobInfo =NULL;

26 EnumJobs(printerHandle, 0, pPrinterInfo->cJobs, 2, NULL, 0,

27 (LPDWORD)&nByteNeeded, (LPDWORD)&nReturned);

28 pJobInfo = (JOB_INFO_2*)malloc(nByteNeeded);

29 ZeroMemory(pJobInfo, nByteNeeded);

30 EnumJobs(printerHandle, 0, pPrinterInfo->cJobs, 2, (LPBYTE)pJobInfo, nByteNeeded,

31 (LPDWORD)&nByteUsed, (LPDWORD)&nReturned);

32

33 //检测当前是否有打印任务

34 if(pPrinterInfo->cJobs == 0)

35 return;

36

37 //纸张类型

38 CString strPageSize = _T("");

39 if(pJobInfo[0].pDevMode->dmPaperSize ==DMPAPER_A4)

40 strPageSize = _T("A4");

41 else if(pJobInfo[0].pDevMode->dmPaperSize ==DMPAPER_B5)

42 strPageSize = _T("B5");

43

44 //打印份数

45 CString strPrintCopies = _T("");

46 strPrintCopies.Format("%d", pJobInfo[0].pDevMode->dmCopies);

47

48 //打印颜色

49 CString strPrintColor = _T("");

50 if(pJobInfo[0].pDevMode->dmColor ==DMCOLOR_COLOR)

51 strPrintColor = _T("彩色");

52 else if(pJobInfo[0].pDevMode->dmColor ==DMCOLOR_MONOCHROME)

53 strPrintColor = _T("黑白");

54

55 //打印时间

56 CString strSubmitted = _T("");

57 strSubmitted.Format("%d-%d-%d %d:%d:%d",

58 pJobInfo[0].Submitted.wYear, pJobInfo[0].Submitted.wMonth, pJobInfo[0].Submitted.wDay,

59 pJobInfo[0].Submitted.wHour+8, pJobInfo[0].Submitted.wMinute, pJobInfo[0].Submitted.wSecond);

60

61   //更新打印机状态列表控件

62 UpdateDataPrinterStatusListCtrl(pJobInfo[0].pDocument, strPageSize,

63 strPrintCopies, strPrintColor, strSubmitted);

64

65 free(pPrinterInfo);

66

67 //关闭打印机设备

68 ClosePrinter(printerHandle);69 }

69c5a8ac3fa60e0848d784a6dd461da6.png

可以看到,在上述代码中,我们首先调用OpenPrinter()函数得到了打印机设备句柄printerHandle,然后通过调用GetPrinter()函数来为PRINTER_INFO_2结构体对象pPrinterInfo赋值,从而进一步通过pPrinterInfo->cJobs得到打印机作业数量。随后,我们通过调用EnumJobs()函数枚举打印任务,为JOB_INFO_2结构体对象pJobInfo赋值。JOB_INFO_2结构体中便存储了我们需要得到的一系列打印机状态信息。最后,我们调用了UpdateDataPrinterStatusListCtrl()函数,将打印机状态信息显示在一个列表控件上。

程序运行结果如图1所示。在打印机选择下拉列表中,会列出当前系统中的所有打印机,选择要监听的打印机之后,点击开始监听按钮,便会创建一个子线程,对打印机状态进行监听(我这里因为没有连接打印机,所以使用的是虚拟打印机Adobe PDF)。当有文档被打印时,打印状态便会实时的显示在列表中。

fad0be9b132a10d3873ed2c36fcc37a8.png

图1 打印机状态监控

由图1可以看出,目前我们已经可以得到打印的文档名称、纸张类型、打印份数、打印颜色以及打印时间这些信息了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值