目前,關於API的應用的文章可以說是遍布各類期刊、雜誌。但是多數執行個體與應用都是基於Visual Basic 的,多數人反映針對於C++ Builder的應用太少,而與列印相關的應用更是少之又少(即使是Visual Basic在這方面的應用可是很少),事實的確如此。這是一篇介紹應用C++ Builder結合Windows API來實現對印表機隊列狀態進行監控的文章。
一、API介紹:
API是Application Programming Interface的縮寫,也就是應用程式調用系統功能的介面。Windows API主要包括系統定義的函數、訊息及與之相關的資料類型。我們使用各種開發工具歸根結底都是和API打交道。
二、與列印狀態相關的API:
Api函數名 函數說明 W3.x W9x NT
EnumJobs 擷取列印工作資訊 否 是 是
OpenPrinter 擷取指定印表機的控制代碼 否 是 是
在 Windows NT 版本以及 Windows 9x 中,增加了一批全新的、專門用來處理印表機及印表機隊列狀態的 API 函數。在這裡,將通過 API 函數 OpenPrinter 與 EnumJobs,來確定印表機列印工作狀態所需的資訊。
OpenPrinter,用來擷取給定印表機的控制代碼,通過該控制代碼可以實現對相應印表機的操作。
函數 EnumJobs,用來列出所指定印表機上正在列印的作業資訊,這裡給定印表機的引用就是通過使用上述OpenPrinter函數反饋回來的印表機控制代碼。
EnumJobs函數介紹:
EnumJobs (ByVal hPrinter As Long, ByVal FirstJob As Long, ByVal NoJobs As Long, ByVal Level As Long, pJob As Long, ByVal cbBuf As Long, pcbNeeded As Long, pcReturned As Long)
API函數EnumJobs用於列舉給定印表機當前所有正在列印的任務狀態資訊,該函數可以列舉給定印表機簡要的或者詳細的(Level決定)隊列任務狀態資訊。在引用該函數時,通常先把cbBuf變數設定為0,以獲得印表機隊列任務的位元組數,該位元組數儲存在pcbNeeded裡以決定pJob變數大小,然後再次引用該函數,獲得印表機隊列任務的詳細資料。
參數:
hPrinter 印表機控制代碼。
FirstJob 統計印表機隊列任務數的起始點,0表示從第一個任務開始統計列舉所有的列印任務。
NoJobs 需要列舉的最大列印任務數。一般設為127。
Level 標示儲存在pJob裡的資訊格式。如果該值為1,資料以JOB_INFO_1的格式儲存;如果該值為2,資料以JOB_INFO_2的格式儲存。
pJob 陣列變數,儲存列印任務的所有資訊;cbBuf設為0時,該值也為0。Level變數的值決定pJob的資料格式(JOB_INFO_1 Or JOB_INFO_2)
cbBuf 該值通常為0。
pcbNeeded 儲存印表機裡列印任務的位元組數。
pcReturned 用來存放列印任務數量的變數。
通過上表可以看出,這兩個API函數只用使用在Windows 9x 以及 Windows NT環境中。
三、開發工具:
C++ Builder作為快速開發Windows平台下應用程式的工具,已經為越來越多的開發人員採用。但是,如果要開發出專業的Windows應用軟體,還需要使用大量的Windows API函數,以下是筆者應用C++ Builder以及Windows API函數來實現對印表機狀態的時時監控。
選擇C++ Builder的理由:
一:由於Windows API 都是用C或C++編寫的,C++ Builder更易於底層應用。
二:C++ Builder對於Windows API的引用更加簡單,這一點是Visual Basic所欠缺的。
四、程式執行個體:
1、啟動C++ Builder程式,新建立一個工程;
2、進入工程,在當前表單分別添加一個CheckListBox控制項、一個Timer控制項;
3、在CheckListBox控制項的Item屬性添加印表機名稱列表(假設在網路中HostPrinter主機上有三台印表機Printer1、Printer2、Printer3),則Item項目裡內容格式為:////HostPrinter//Printer1、////HostPrinter////Printer2、////HostPrinter////Printer3 ;
4、Timer的Interval屬性設定為60000(一分鐘),在Timer的OnTimer事件加入如下代碼:
{
HANDLE hPrinter; //印表機控制代碼
JOB_INFO_2 jobs[30]; //保留列印工作詳細資料
DWORD size=sizeof(jobs);
JOB_INFO_2 *jobs1=NULL; //動態數組用於對大於size的任務進行操作
DWORD pcbNeeded=0; //所有列印位元組數
int actNeed=0;
DWORD pcReturned=0; //列印任務數
char buf[19]; //指向印表機或機器名
int ret1; //獲得印表機控制代碼傳回值
int ret; //獲得印表機任務傳回值
TDateTime startTime;
Word Hour=0;
Word Hour1=0;
Word Min=0;
Word Min1=0;
Word Sec=0;
Word MSec=0;
int StartTime=0; //任務開始時間
int NowTime=0; //目前時間
int TotalTime=0; //任務停留時間
String str;
int length;
int PrintCount;
int InitCount=15; //設定的列印佇列數量--------警示底線
int InitTime=10; //設定的列印佇列事件--------警示底線(分鐘)
PrintCount =CheckListBox1->Count ;
for (int i=0; i < PrintCount; i++)
{
//..............取得列表裡的印表機
str=CheckListBox1->Items->Strings ;
length=str.Length() ;
//................字串到字元的轉換,
StrPLCopy(buf,str,length);
//................獲得印表機控制代碼
ret1= OpenPrinter(buf, &hPrinter, NULL);
//................獲得列印任務數
ret= EnumJobs(hPrinter, 0, 127, 2,0, 0, &pcbNeeded, &pcReturned);
//必要的一步,先取出印表機裡任務的位元組數,然後決定jobs1變數大小。
//--------------------------①
//.................重定義Jobs1, 根據pcbNeeded決定使用哪個變數
if (pcbNeeded>size)
{
actNeed=pcbNeeded;
jobs1=new JOB_INFO_2[actNeed];
ret= EnumJobs(hPrinter, 0, 127, 2,(LPBYTE)jobs1, actNeed, &pcbNeeded, &pcReturned);
startTime=SystemTimeToDateTime(jobs1[0].Submitted); //------------------②
delete jobs1;
}
else
{
ret= EnumJobs(hPrinter, 0, 127, 2,(LPBYTE)jobs, size, &pcbNeeded, &pcReturned);//-----------------------------③
if (pcReturned>0)
startTime=SystemTimeToDateTime(jobs[0].Submitted);
}
//.................pcbNeeded>size結束
//................如果隊列裡有列印任務,比對數量與時間
if (pcReturned>0)
{
//.................時間轉換,計算一天內的時間差
{
//............時間比較運算處理;
//............時間轉換StartTime轉換成分鐘
}
DecodeTime(Now(),Hour1, Min1, Sec,MSec);
NowTime=Hour1*60+Min1;
TotalTime=NowTime-StartTime;
}
//依據條件判斷是否警示
if ((pcReturned>InitCount) |(TotalTime >InitTime))
{
Beep();
}
pcReturned=0;
pcbNeeded=0;
}
//..........................pcReturned>0結束
}//....................................................for結束
5、編譯並運行上述程式:
①程式中,此處的獲得印表機任務的目的主要是獲得印表機作業的位元組數------ pcbNeeded,該變數裡位元組的大小,將決定進一步獲得印表機裡作業的狀態時所用的變數是Jobs還是Jobs1。
②當pcbNeeded>size,給Jobs1分配空間,然後獲得印表機當前作業的狀態。
③當pcbNeeded<size,用Jobs作為變數,獲得當前印表機作業狀態。
註:②、③參數引用與①不同。
五、應用分析:
可以說IT技術在製造業得到了廣泛的應用,而列印控制與監控則是製造業中眾多應用中的較為典型的應用。通常,在生產製造過程中,都有很多印表機用於列印生產排序單、裝配單、銘牌、標籤等等。因此印表機的時時狀態(缺紙、墨盡、卡紙)在這裡就顯得尤為重要了,如果不能及時的監控到印表機的狀態勢必會影響生產的正常持續運行。所以為了保證生產正常運行擁有一套用於監控印表機時時狀態的程式是很有必要的。