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

C# WinForm 完整列印功能實作:PrintDocument、頁面設定、預覽、多頁分頁邏輯

     編輯:關於C語言

前言

WinForm 列印核心類別為 System.Drawing.Printing.PrintDocument,封裝印表機設定、頁面設定、列印事件與分頁邏輯。本文完整實作:列印設定、頁面設定、列印預覽、正式列印、多頁分頁核心邏輯。

一、核心類別與屬性

二、PrintPageEventArgs 關鍵屬性

屬性/事件用途
PrinterSettings印表機設定(由 PrintDialog 取得)
PrintController控制列印流程
DefaultPageSettings頁面設定(由 PageSetupDialog 取得)
DocumentName顯示於印表機佇列的文件名
BeginPrint列印開始前觸發(初始化)
PrintPage核心事件:每頁觸發一次,繪製內容
Print()啟動列印

三、完整實作程式碼

using System;
using System.Drawing;
using System.Drawing.Printing;
using System.IO;
using System.Windows.Forms;

public partial class NotepadForm : Form
{
    private PrintDocument _printDoc;
    private StringReader _lineReader; // 追蹤讀取位置
    
    public NotepadForm()
    {
        InitializeComponent();
        InitializePrinting();
    }
    
    private void InitializePrinting()
    {
        _printDoc = new PrintDocument();
        _printDoc.DocumentName = "記事本文件";
        _printDoc.PrintPage += PrintDoc_PrintPage;
    }
    
    // ========== 核心分頁邏輯 ==========
    private void PrintDoc_PrintPage(object sender, PrintPageEventArgs e)
    {
        Graphics g = e.Graphics;
        Font printFont = textBox.Font;
        Brush brush = Brushes.Black;
        
        float linesPerPage = e.MarginBounds.Height / printFont.GetHeight(g);
        float yPos = e.MarginBounds.Top;
        float xPos = e.MarginBounds.Left;
        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, xPos, yPos);
            count++;
        }
        
        // 還有內容未列印完 → 觸發下一頁
        e.HasMorePages = (line != null);
    }
    
    // ========== 列印設定 ==========
    private void Menu_PrintSetup_Click(object sender, EventArgs e)
    {
        using (var dlg = new PrintDialog())
        {
            dlg.Document = _printDoc; // 同步設定到 PrintDocument
            dlg.ShowDialog();
        }
    }
    
    // ========== 頁面設定 ==========
    private void Menu_PageSetup_Click(object sender, EventArgs e)
    {
        using (var dlg = new PageSetupDialog())
        {
            dlg.Document = _printDoc;
            dlg.ShowDialog();
        }
    }
    
    // ========== 列印預覽 ==========
    private void Menu_PrintPreview_Click(object sender, EventArgs e)
    {
        _lineReader = new StringReader(textBox.Text); // 重置讀取位置
        
        using (var dlg = new PrintPreviewDialog())
        {
            dlg.Document = _printDoc;
            dlg.WindowState = FormWindowState.Maximized;
            try
            {
                dlg.ShowDialog();
            }
            catch (Exception ex)
            {
                MessageBox.Show($"預覽錯誤: {ex.Message}", "錯誤", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
    }
    
    // ========== 正式列印 ==========
    private void Menu_Print_Click(object sender, EventArgs e)
    {
        _lineReader = new StringReader(textBox.Text); // 重置讀取位置
        
        using (var dlg = new PrintDialog())
        {
            dlg.Document = _printDoc;
            if (dlg.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    _printDoc.Print();
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"列印錯誤: {ex.Message}", "錯誤", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }
    }
}

四、分頁邏輯深度解析

關鍵變數

  • _lineReader:類別層級,跨 PrintPage 事件保持讀取位置
  • linesPerPage:MarginBounds.Height / Font.Height,每頁可容納行數
  • yPos:每行垂直座標,Top + 行號 * 行高

流程圖解


Print() 呼叫
    ↓
PrintPage 事件 (第 1 頁)
    ↓
while (行數 < linesPerPage && 讀取下一行)
    繪製該行
    行數++
    ↓
若 讀取到 null (內容結束)
    HasMorePages = false → 列印結束
若 讀取非 null (還有內容)
    HasMorePages = true → 觸發下一次 PrintPage
    ↓
PrintPage 事件 (第 2 頁) ... 循環直到 HasMorePages = false

五、常見問題與解決

屬性說明
Graphics頁面繪圖介面,呼叫 DrawString、DrawImage 等
MarginBounds可列印區域矩形(含邊界)
PageBounds整頁紙張矩形
HasMorePages關鍵:true=繼續下一頁,false=結束列印
Cancel設 true 取消列印

六、進階擴展

  • 頁首/頁尾:在 PrintPage 繪製頁碼、標題、日期
  • 表格/圖片列印:計算欄寬、DrawImage、分頁斷行處理
  • 異步列印:PrintDocument.PrintController 自訂
  • 報表元件:複雜報表建議用 ReportViewer、FastReport、Stimulsoft

七、總結

WinForm 列印核心三步驟:

  1. 建立 PrintDocument,掛接 PrintPage 事件
  2. 實作 PrintPage:Graphics.DrawString + HasMorePages 分頁控制
  3. 搭配 PrintDialog/PageSetupDialog/PrintPreviewDialog 提供使用者設定

掌握 StringReader 追蹤位置 + HasMorePages 遞迴觸發,即掌握多頁列印精髓。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
問題原因解決
只列印第一頁HasMorePages 未設 true檢查 line != null 邏輯
內容重複/遺漏_lineReader 未重置或共用錯誤每次列印/預覽前 new StringReader(text)
字型/大小不符使用預設字型而非 TextBox 字型Font printFont = textBox.Font
中文亂碼字型不支援中文使用 Microsoft JhengHei / SimSun 等
預覽與列印不同預覽未重置 _lineReader兩者前均重置