總結工作需要,目前在開發印表機sdk,該篇主要是記錄獲取列印檔案的頁數的功能,其他功能後續逐漸完善
windows列印使時,會建立乙個列印佇列,電腦狀態列會出現乙個列印佇列圖示,雙擊開啟,如下圖所示:
列印佇列裡面有文件名(有的系統可能帶路徑)、狀態、頁數等資訊,並且會有多個任務;使用windows api可以獲取列印佇列的資訊
通過windows api獲取到列印佇列作業結構體job_info_2,該結構體包含文件名、列印狀態、和頁數等資訊;可以通過匹配文件名,找到對應的列印作業,獲取列印頁數,但不能直接獲取該頁數作為文件頁數;因為,列印文件的時候,系統會將文件載入到印表機驅動,由印表機驅動來計算文件頁數,如果列印檔案很大,文件載入需要一定的耗時,而列印驅動計算文件頁數是載入多少,則計算多少頁數,所以不能立即獲取返回,需要等待文件載入完成
另外,系統載入文件到印表機驅動的同時,會將部分已經載入完成的文件資源傳送給印表機進行列印,也可以根據自己需要,等待文件載入完成之後在列印,示例**中有說明
**如下(示例):
#include
#include
#include
#pragma comment(lib, "shlwapi.lib")
// 獲取列印佇列中的所有任務
bool getjobs
(handle hprinter, job_info_2 *
* ppjobinfo,
int* pcjobs, dword * pstatus)
} pprinterinfo =
(printer_info_2 *
)malloc
(cbyteneeded);if
(!(pprinterinfo)
)// 取得與指定印表機有關的資訊printer_info_2if(
!getprinter
(hprinter,2,
(lpbyte)pprinterinfo, cbyteneeded,
&cbyteused)
)// 獲取pjobstorage資料結構的尺寸if(
!enumjobs
(hprinter,
0, pprinterinfo-
>cjobs,2,
null,0
,(lpdword)
&cbyteneeded,
(lpdword)
&nreturned))}
pjobstorage =
(job_info_2 *
)malloc
(cbyteneeded);if
(!pjobstorage)
zeromemory
(pjobstorage, cbyteneeded)
;// 列舉列印佇列中的作業if(
!enumjobs
(hprinter,0,
pprinterinfo-
>cjobs,2,
(lpbyte)pjobstorage,
cbyteneeded,
(lpdword)
&cbyteused,
(lpdword)
&nreturned)
)*pcjobs = nreturned;
*pstatus = pprinterinfo-
>status;
*ppjobinfo = pjobstorage;
free
(pprinterinfo)
;return true;
}// 功能:通過檔名獲取檔案列印頁數
// 引數:
// [in/out] i*****count 列印檔案頁數
// [in] pcurprintfilename 列印檔案名
// 返回:成功返回0,其他失敗
intget*****count
(int
& i*****count,
const
char
* pcurprintfilename)
// 獲取預設印表機名
dword dwnamelen = max_path;
tchar szprintername[max_path]=;
getdefaultprinter
(szprintername,
&dwnamelen)
;// 通過印表機名開啟印表機裝置
handle hprinter =
null
; bool bret =
openprinter
(szprintername,
&hprinter,
null);
if(!bret)
dword dwprinterstatus;
job_info_2 *pjobinfo;
i*****count =0;
char
* pfilename =
null
;// 儲存要查詢的檔案在列印佇列中序號
int ifindjobindex =-1
;// 列印佇列的總檔案數量
int ijobnum =0;
// 列印佇列任務id,通過id來區分是那一條列印任務,當前儲存暫停列印的任務id
int ipausejobid =-1
;int icurtotal =0;
long ncurwaitprintpagenum =0;
// 預設返回超時
long iret =4;
// 獲取待列印檔案頁數最大超時等待時間(單位:秒),根據自己需要可以傳參配置,示例只提供乙個預設值
dword dwwaitget*****time =10;
dword dwstartwaittime =
gettickcount()
;while((
gettickcount()
- dwstartwaittime)
< dwwaitget*****time *
1000
) ifindjobindex =-1
;// 迴圈遍歷列印佇列,可能存在多個檔案在排隊列印
for(
int i =
0; i < ijobnum; i++
)// 獲取當前列資訊中列印檔案名,不同系統可能有差異,有的系統檔名帶路徑,有些不帶,故只取檔名
pfilename =
pathfindfilename
(pjobinfo[i]
.pdocument)
;// 如果當前列檔名不為空,且匹配成功,則跳出迴圈
if(pfilename !=
null
&&stricmp
(pcurprintfilename, pfilename)==0
)}// 沒有查詢到,則進行下一次迴圈
if(ifindjobindex !=-1
)// 當前控制面板列印任務和下發列印任務檔名一致,並且列印狀態不是異常
if(pjobinfo[ifindjobindex]
.status & job_status_printing || pjobinfo[ifindjobindex]
.status & job_status_complete ||
pjobinfo[ifindjobindex]
.status & job_status_printed)
// 如果頁數變化,儲存當前佇列中的頁數
if(ncurwaitprintpagenum != pjobinfo[ifindjobindex]
.totalpages)
// 如果獲取到列印佇列中的頁數不再改變,並且連續30次(根據自己需要配置),則認為列印任務已經載入完成
if(icurtotal <30)
// 儲存最終的列印檔案總頁數
i*****count = ncurwaitprintpagenum;
// 退出迴圈
iret =0;
break;}
}// 儲存列印檔案總頁數,但是可能沒有統計完成
i*****count = ncurwaitprintpagenum;
// 恢復暫停的列印任務
if(ipausejobid !=-1
)// 關閉印表機
closeprinter
(hprinter)
;return iret;
}
該功能主要是獲取列印檔案頁數,基本能滿足工作需要;但是對於市場中各種複雜的執行環境,有時候會出現獲取不到列印檔案頁數的情況,反覆除錯記錄日誌跟蹤發現,對於效能很好的電腦,並且列印檔案頁數很少時,系統將文件載入到印表機驅動併發送到印表機耗時很短,之後列印檔案作業也將關閉,如果此時來獲取列印頁數,肯定獲取不到,強行背鍋?,所以我這邊的建議是,在執行列印之前,開闢乙個執行緒去查詢列印檔案頁數,具體就不詳述了
獲取列印頁數不准,更好的方案請參考我這篇部落格c++設定印表機暫停列印setprinter,完美解決該問題
codevs2640 列印頁數
貪心,不知道怎麼想的就大師難度了 有些細節需要處理一下 首先是注意一行可能有多個標註,用inc記錄,初始值付成1.另乙個陣列存好多個k 0 只是覺得比較方便,反正資料弱 表示每一頁 反正不會超過n,誰叫你說一定有解呢,就是人性,哼 用指標d記錄列印到了第幾頁 var f,t array 0.5000...
C 列印word檔案
region 輔助定義 印表機狀態 flagsattribute internal enum printerstatus structlayout layoutkind.sequential,charset charset.auto internal struct structprinterdefa...
C語言列印檔案
include includevoid main int printfile char filename int fputc int c,file fp c 要寫入的字元,雖然定義為整形,但只能使用最低位的乙個位元組。fp是檔案指標 函式功能 將字元c輸出到fp所指向的檔案 int fgetc fi...