| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426 |
- using FileInfoClass;
- using PdfiumViewer;
- using System;
- using System.Drawing;
- using System.Drawing.Printing;
- using System.IO;
- using System.Threading.Tasks;
- using System.Windows.Forms;
- namespace prBrowser
- {
- class PrintPdf
- {
- Control _uiContext;
- private int totalPageSize = 0;
- private int currentPageIndex = 0;
- float dpiX = 150;
- float dpiY = 150;
- //int printableWidth = 0;
- //int printableHeight = 0;
- private PrintDocument myPrintDocument;
- private PdfiumViewer.PdfDocument pdfDocument;
- private PrintSettings settings;
- string tempPdfPath = string.Empty;
- private PrintState _currentState = PrintState.Ready;
- private readonly object _stateLock = new object();
- string logPath = @"C:\ProgramData\prykNT\prBrowser\bin\service\log\test.log";
- FileClass fileclass = new FileClass();
- // 打印模式枚举
- private enum PrintMode
- {
- SinglePage,
- MultiPage
- }
- // 打印状态机
- private enum PrintState
- {
- Ready,
- PrintingPage,
- WaitingUserConfirmation,
- Completed,
- Cancelled
- }
- private PrintMode _printMode = PrintMode.SinglePage;
- // 设置打印模式
- public void SetPrintMode(bool singlePageMode)
- {
- _printMode = singlePageMode ? PrintMode.SinglePage : PrintMode.MultiPage;
- }
- // 安全的状态切换
- private void ChangeState(PrintState newState)
- {
- lock (_stateLock)
- {
- _currentState = newState;
- }
- }
- // 启动打印
- public void StartPrinting()
- {
- lock (_stateLock)
- {
- if (_currentState == PrintState.Ready)
- {
- currentPageIndex = 0;
- ChangeState(PrintState.PrintingPage);
- myPrintDocument.Print();
- }
- }
- }
- // 用户确认继续打印
- public void UserConfirmContinue()
- {
- lock (_stateLock)
- {
- if (_currentState == PrintState.WaitingUserConfirmation)
- {
- ChangeState(PrintState.PrintingPage);
- // 直接启动下一页打印
- if (currentPageIndex < totalPageSize)
- {
- myPrintDocument.Print();
- }
- }
- }
- }
- // 用户取消打印
- public void UserCancel()
- {
- ChangeState(PrintState.Cancelled);
- Dispose();
- }
- public void Print(string pdfPath, PrintSettings settings)
- {
- this.settings = settings;
- try
- {
- tempPdfPath = pdfPath;
- pdfDocument = PdfDocument.Load(tempPdfPath);
- //pdfDocument.Save("d:\\test.pdf");
-
- totalPageSize = pdfDocument.PageCount;
- //printableWidth = this.settings.printerSettings.DefaultPageSettings.PaperSize.Width * 3;
- //printableHeight = (int)(this.settings.printerSettings.DefaultPageSettings.PaperSize.Height * 2.9);
- // 根据页数和设置决定打印模式
- bool useSinglePageMode = totalPageSize > 1 && (settings.manualDuplex && "all".Equals(settings.duplexTips));
- fileclass.WriteLogFile(logPath, $"Print.useSinglePageMode:{useSinglePageMode}");
- SetPrintMode(useSinglePageMode);
- initPrinter();
- // 启动打印
- StartPrinting();
- }
- catch (Exception ex)
- {
- ShowErrorMessage(ex.Message);
- }
- }
- private void initPrinter()
- {
- myPrintDocument = new PrintDocument();
- myPrintDocument.PrintPage += new PrintPageEventHandler(myPrintDocument_PrintPage);
- myPrintDocument.EndPrint += new PrintEventHandler(myPrintDocument_EndPrint);
- StandardPrintController standardPrint = new StandardPrintController();
- myPrintDocument.DefaultPageSettings = this.settings.printerSettings.DefaultPageSettings;
- myPrintDocument.PrinterSettings = this.settings.printerSettings;
- myPrintDocument.PrintController = standardPrint;
-
- }
- private void myPrintDocument_PrintPage(object sender, PrintPageEventArgs e)
- {
- try
- {
- lock (_stateLock)
- {
- if (currentPageIndex >= totalPageSize || _currentState != PrintState.PrintingPage)
- {
- e.HasMorePages = false;
- return;
- }
- Rectangle printArea = e.MarginBounds;
- if (printArea.Width <= 0 || printArea.Height <= 0)
- printArea = new Rectangle(0, 0, e.PageBounds.Width, e.PageBounds.Height);
- else
- printArea = new Rectangle(0, 0, printArea.Width, printArea.Height);
- // 针对 2.pdf 这类发票:假设有效内容在左上角 500x300 points 区域
- // A4 = 595x842 points,我们只取 (0,0,500,300)
- float cropWidthPoints = 250; // 根据实际调整
- float cropHeightPoints = 150;
- // 转为像素
- int renderWidth = (int)((cropWidthPoints / 72f) * e.Graphics.DpiX);
- int renderHeight = (int)((cropHeightPoints / 72f) * e.Graphics.DpiY);
- using (Image image = pdfDocument.Render(
- currentPageIndex,
- renderWidth,
- renderHeight,
- e.Graphics.DpiX,
- e.Graphics.DpiY,
- PdfRenderFlags.Annotations | PdfRenderFlags.ForPrinting))
- {
- // 等比缩放并居中(或拉伸)
- float scaleX = (float)printArea.Width / image.Width;
- float scaleY = (float)printArea.Height / image.Height;
- float scale = Math.Min(scaleX, scaleY); // 保持比例
- int drawW = (int)(image.Width * scale);
- int drawH = (int)(image.Height * scale);
- int x = ((printArea.Width - drawW) / 2) - 10;
- int y = (printArea.Height - drawH) / 2;
- fileclass.WriteLogFile(logPath, $"[RENDER] Drawing page {currentPageIndex} to printer");
- e.Graphics.DrawImage(image, x, y, drawW, drawH);
- //string debugImagePath = $@"C:\temp\debug_page_{currentPageIndex}.png";
- //image.Save(debugImagePath, System.Drawing.Imaging.ImageFormat.Png);
- //fileclass.WriteLogFile(logPath, $"[DEBUG SAVE] Saved {debugImagePath}");
- }
- //printableWidth = this.settings.printerSettings.DefaultPageSettings.PaperSize.Width * 3;
- //printableHeight = (int)(this.settings.printerSettings.DefaultPageSettings.PaperSize.Height * 2.9);
- // 根据页数和设置决定打印模式
- bool useSinglePageMode = totalPageSize > 1 && (settings.manualDuplex && "all".Equals(settings.duplexTips));
- fileclass.WriteLogFile(logPath, $"myPrintDocument_PrintPage.useSinglePageMode:{useSinglePageMode}");
- fileclass.WriteLogFile(logPath, $"myPrintDocument_PrintPage.totalPageSize:{totalPageSize}");
- fileclass.WriteLogFile(logPath, $"myPrintDocument_PrintPage.currentPageIndex:{currentPageIndex}");
- //e.HasMorePages = false;
- e.HasMorePages = (currentPageIndex + 1) < totalPageSize;
- currentPageIndex++;
- }
- }
- catch (Exception ex)
- {
- ChangeState(PrintState.Cancelled);
- e.Cancel = true;
- ShowErrorMessage($"打印错误: {ex.Message}");
- }
- }
- private void myPrintDocument_EndPrint(object sender, PrintEventArgs e)
- {
- try
- {
- lock (_stateLock)
- {
- if (_currentState == PrintState.Cancelled)
- {
- Dispose();
- return;
- }
- //currentPageIndex++;
- // 检查是否完成
- if (currentPageIndex >= totalPageSize)
- {
- ChangeState(PrintState.Completed);
- Dispose();
- return;
- }
- // 根据打印模式处理下一页
- ChangeState(PrintState.WaitingUserConfirmation);
- if (NeedDuplexPrompt(currentPageIndex))
- {
- Task.Delay(500).ContinueWith(_ =>
- {
- _uiContext?.BeginInvoke(new Action(() =>
- {
- if (_currentState == PrintState.WaitingUserConfirmation)
- {
- // 提示
- ShowUserPrompt();
- }
- }));
- });
- }
- else {
- // 直接打印
- UserConfirmContinue();
- }
- }
- }
- catch (Exception ex)
- {
- ShowErrorMessage($"结束打印错误: {ex.Message}");
- Dispose();
- }
- }
- private bool NeedDuplexPrompt(int pageIndex)
- {
- if (!settings.manualDuplex) return false;
- bool isEvenPage = (pageIndex % 2 == 1);
- return ("all".Equals(settings.duplexTips)) ||
- ("even".Equals(settings.duplexTips) && isEvenPage);
- }
- private void ShowUserPrompt()
- {
- if (_uiContext?.InvokeRequired == true)
- {
- _uiContext.BeginInvoke(new Action(ShowUserPrompt));
- return;
- }
- //DialogResult result = showConfirmDialog();
- DialogResult result = MessageBox.Show($"请更背面,点击'是(Y)'继续打印第 {currentPageIndex + 1} 页", "打印确认", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
- if (result == DialogResult.Yes)
- {
- UserConfirmContinue();
- }
- else
- {
- UserCancel();
- }
- }
- private DialogResult showConfirmDialog() {
- var promptForm = new Form
- {
- Width = 400,
- Height = 150,
- FormBorderStyle = FormBorderStyle.FixedDialog,
- Text = _printMode == PrintMode.SinglePage ? "打印确认" : "双面打印确认",
- StartPosition = FormStartPosition.CenterParent
- };
- string promptText = $"请更换纸张,点击确认继续打印第 {currentPageIndex + 1} 页";
- var label = new Label
- {
- Text = promptText,
- Dock = DockStyle.Top,
- TextAlign = ContentAlignment.MiddleCenter,
- Height = 50
- };
- var yesBtn = new Button { Text = "确认", DialogResult = DialogResult.Yes, Dock = DockStyle.Left, Width = 180 };
- var noBtn = new Button { Text = "取消", DialogResult = DialogResult.No, Dock = DockStyle.Right, Width = 180 };
- yesBtn.Click += (s, e) => { promptForm.DialogResult = DialogResult.Yes; promptForm.Close(); };
- noBtn.Click += (s, e) => { promptForm.DialogResult = DialogResult.No; promptForm.Close(); };
- var panel = new Panel { Dock = DockStyle.Bottom, Height = 35 };
- panel.Controls.Add(yesBtn);
- panel.Controls.Add(noBtn);
- promptForm.Controls.Add(label);
- promptForm.Controls.Add(panel);
- var result = promptForm.ShowDialog(_uiContext);
- return result;
- }
- private void ShowErrorMessage(string message)
- {
- if (_uiContext.InvokeRequired)
- {
- _uiContext.Invoke(new Action<string>(ShowErrorMessage), message);
- return;
- }
- MessageBox.Show(message, "打印错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
- }
- private void DisposePdfDocument()
- {
- if (pdfDocument != null)
- {
- pdfDocument.Dispose();
- pdfDocument = null;
- }
- }
- protected void DisposePrint(bool disposing)
- {
- if (disposing && myPrintDocument != null)
- {
- try
- {
- myPrintDocument.PrintPage -= myPrintDocument_PrintPage;
- myPrintDocument.EndPrint -= myPrintDocument_EndPrint;
- myPrintDocument.Dispose();
- myPrintDocument = null;
- }
- catch (Exception ex)
- {
- // 记录日志但不抛出异常,避免在Dispose过程中出现问题
- System.Diagnostics.Debug.WriteLine($"DisposePrint error: {ex.Message}");
- }
- }
- }
- public void Dispose()
- {
- try
- {
- ChangeState(PrintState.Cancelled);
- DisposePdfDocument();
- DisposePrint(true);
-
- // 清理临时文件
- if (!string.IsNullOrEmpty(tempPdfPath) && File.Exists(tempPdfPath))
- {
- try
- {
- File.Delete(tempPdfPath);
- }
- catch (Exception ex)
- {
- System.Diagnostics.Debug.WriteLine($"Failed to delete temp PDF: {ex.Message}");
- }
- }
- }
- catch (Exception ex)
- {
- System.Diagnostics.Debug.WriteLine($"Dispose error: {ex.Message}");
- }
- }
- }
- }
|