C 獲取列印檔案頁數

2021-10-24 20:22:00 字數 4486 閱讀 1950

總結工作需要,目前在開發印表機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...