Windows 將顯示器、印表機、繪圖儀視為輸出裝置,預設為顯示器。列印本質:建立指向印表機的裝置環境(DC),繪圖函式輸出內容至 DC,完成後刪除 DC。
Win.ini [windows] 區段 device 鍵值格式:
device=HP LaserJet 4050 (computer000),HPBFDB1,LPT1
// 印表機名稱, 驅動程式名稱, 輸出埠
使用 GetProfileString 讀取:
char szPrinter[80];
GetProfileString("windows", "device", ",,,", szPrinter, 80);
char *szDevice, *szDriver, *szOutput;
if ((szDevice = strtok(szPrinter, ",")) &&
(szDriver = strtok(NULL, ",")) &&
(szOutput = strtok(NULL, ","))) {
HDC hdcPrint = CreateDC(szDriver, szDevice, szOutput, NULL);
// 成功則 hdcPrint 為有效印表機 DC
}
StartDoc(hdcPrint, &di),DOCINFO 結構指定文件名稱。StartPage(hdcPrint) 通知印表機走紙準備。TextOut、LineTo、BitBlt 等 GDI 函式,與螢幕繪圖完全一致。EndPage(hdcPrint) 停止走紙。EndDoc(hdcPrint) 完成列印工作。DeleteDC(hdcPrint) 釋放 DC。
void CTestDlg::OnPrint() {
char szPrinter[80];
char *szDevice, *szDriver, *szOutput;
HDC hdcPrint;
static DOCINFO di = { sizeof(DOCINFO), "PrinterTest", NULL, NULL, 0 };
GetProfileString("windows", "device", ",,,", szPrinter, 80);
if ((szDevice = strtok(szPrinter, ",")) &&
(szDriver = strtok(NULL, ",")) &&
(szOutput = strtok(NULL, ","))) {
if ((hdcPrint = CreateDC(szDriver, szDevice, szOutput, NULL)) != NULL) {
if (StartDoc(hdcPrint, &di) > 0) {
StartPage(hdcPrint);
SaveDC(hdcPrint);
TextOut(hdcPrint, 100, 100, "熱烈祝賀列印功能實作成功!", 18);
RestoreDC(hdcPrint, -1);
EndPage(hdcPrint);
EndDoc(hdcPrint);
MessageBox("列印完成!", "提示", MB_ICONINFORMATION);
}
DeleteDC(hdcPrint);
} else {
MessageBox("無預設印表機或未安裝印表機!");
}
}
}
CreateFont / SelectObject 切換字型、大小、粗細。BitBlt 輸出位圖,StretchBlt 縮放列印。StartPage/EndPage,計算分頁邏輯。CPrintDialog 讓使用者選擇印表機與設定。OnPreparePrinting、OnPrint、OnBeginPrinting、OnEndPrinting 實現完整列印框架支援。| 錯誤碼 | 原因 | 對策 |
|---|---|---|
| DISP_CHANGE_FAILED | CreateDC 失敗 | 檢查印表機名稱、驅動程式、埠號是否正確 |
| StartDoc 回傳 ≤ 0 | 文件啟動失敗 | 檢查 DOCINFO 結構、印表機是否離線 |
| 文字亂碼 | 字碼頁不符 | 使用 Unicode 版 API(TextOutW)或設定正確字碼頁 |
掌握「取得印表機資訊 → 建立 DC → 文件/頁面流程控制 → GDI 輸出 → 清理」五步驟,即可在 VC++ 6.0 靈活實作從簡單文字到複雜報表的各類列印需求。