首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# WinForms 完整打印功能實現指南

     編輯:關於C語言

打印功能四大核心模塊

在 Windows 應用中,完整打印功能通常包含:

  1. 打印設置:選擇打印機、紙張來源、份數等 (PrintDialog)
  2. 頁面設置:紙張大小、方向、邊距 (PageSetupDialog)
  3. 打印預覽:所見即所得預覽 (PrintPreviewDialog)
  4. 正式打印:發送到打印機 (PrintDocument.Print)

核心類:PrintDocument

System.Drawing.Printing.PrintDocument 封裝所有打印邏輯,關鍵成員:

成員說明
PrinterSettings打印機設置(由 PrintDialog 自動填充)
DefaultPageSettings頁面設置(由 PageSetupDialog 自動填充)
DocumentName顯示在打印隊列中的文檔名
PrintPage 事件核心繪制邏輯,每頁觸發一次
BeginPrint/EndPrint 事件打印開始/結束時觸發,可做初始化/清理
Print() 方法啟動打印流程

PrintPage 事件核心邏輯

事件參數 PrintPageEventArgs 提供:

  • Graphics:頁面繪圖面
  • MarginBounds:可打印區域(不含邊距)
  • PageBounds:整頁物理大小
  • HasMorePages:設置 true 觸發下一頁

文本分頁打印標準模式


private StringReader lineReader; // 類級字段,保持讀取位置

private void printDocument_PrintPage(object sender, PrintPageEventArgs e)
{
    Graphics g = e.Graphics;
    Font printFont = textBox.Font; // 要打印的字體
    SolidBrush brush = new SolidBrush(Color.Black);
    
    float linesPerPage = e.MarginBounds.Height / printFont.GetHeight(g);
    float yPos = e.MarginBounds.Top;
    int count = 0;
    string line;
    
    // 逐行打印當前頁
    while (count < linesPerPage && ((line = lineReader.ReadLine()) != null))
    {
        yPos = e.MarginBounds.Top + count * printFont.GetHeight(g);
        g.DrawString(line, printFont, brush, e.MarginBounds.Left, yPos);
        count++;
    }
    
    // 還有內容則設置 HasMorePages=true,觸發下一次 PrintPage
    e.HasMorePages = (line != null);
}

四大功能的統一調用模式

所有對話框均通過 Document 屬性關聯同一 PrintDocument 實例:


// 打印設置
private void MenuPrintSetup_Click(object sender, EventArgs e)
{
    using (PrintDialog dlg = new PrintDialog { Document = printDocument })
        dlg.ShowDialog();
}

// 頁面設置
private void MenuPageSetup_Click(object sender, EventArgs e)
{
    using (PageSetupDialog dlg = new PageSetupDialog { Document = printDocument })
        dlg.ShowDialog();
}

// 打印預覽
private void MenuPrintPreview_Click(object sender, EventArgs e)
{
    lineReader = new StringReader(textBox.Text); // 重置讀取器
    using (PrintPreviewDialog dlg = new PrintPreviewDialog { Document = printDocument })
    {
        try { dlg.ShowDialog(); }
        catch (Exception ex) { MessageBox.Show(ex.Message, "預覽錯誤"); }
    }
}

// 正式打印
private void MenuPrint_Click(object sender, EventArgs e)
{
    lineReader = new StringReader(textBox.Text);
    using (PrintDialog dlg = new PrintDialog { Document = printDocument })
    {
        if (dlg.ShowDialog() == DialogResult.OK)
        {
            try { printDocument.Print(); }
            catch (Exception ex) { MessageBox.Show(ex.Message, "打印錯誤"); }
        }
    }
}

進階主題

打印圖片/表格/報表

  • 圖片:g.DrawImage(image, rect),注意縮放比例與分頁
  • 表格:手動計算單元格座標,DrawRectangle+DrawString
  • 複雜報表:建議使用 ReportViewer (RDLC) 或第三方庫 (FastReport, Stimulsoft)

異步打印與進度反饋

PrintDocument.Print 是同步阻塞的。大文檔建議:

  1. 在 BackgroundWorker/Task 中調用 Print
  2. 利用 PrintPage 事件報告進度(當前頁/總頁數)
  3. UI 線程顯示進度條,支持取消(設置 e.Cancel = true)

常見坑點

  • 字體不可用:目標打印機/系統缺少字體導致替換,建議嵌入字體或使用系統通用字體
  • 邊距單位:MarginBounds 單位為 1/100 英寸,與 Graphics 默認單位 (1/100 英寸) 一致
  • 預覽與打印不一致:確保 lineReader 在預覽和打印前均重置
  • 跨線程調用:打印事件在線程池線程觸發,若訪問 UI 控件需 Invoke

總結

掌握 PrintDocument + PrintPage 事件驅動模型,配合三大對話框,即可實現專業級打印功能。關鍵在於正確處理分頁邏輯(HasMorePages)、資源管理(using 釋放筆刷/字體)與異常捕獲。複雜排版場景請引入專業報表組件。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved