以高于屏幕分辨率的 dpi 打印表格
Print a Form at higher dpi than screen resolution
问题:
我们需要有关如何使用 WinForms 自动缩放到不同 DPI 的能力的帮助,以允许我们以 600dpi 而不是屏幕 DPI 打印表单。
对于所见即所得的打印,我们只是简单地采用我们精心布置的 window 并打印它(关闭滚动条和按钮等)。效果很好,除了一件事:它以 96dpi 或 120dpi 显示(无论屏幕分辨率是多少)……两者都看起来粗糙且不专业(我们的客户抱怨)。尽管它与屏幕上的内容一样可读,但您希望印刷文档比屏幕上的文档更具可读性……您希望能够看到更多详细信息,能够阅读较小的文本等。
考虑的备选方案:
鉴于我们的自动缩放效果很好,因此我们的 window 在 96dpi、120dpi、144 dpi 等分辨率下看起来不错,我们希望我们可以在 600dpi 下绘制 window然后打印出来。
或者,我们着眼于将 window 离屏画得比正常大 5-6 倍,以便我们拥有与 600dpi 相同数量的像素,但分辨率为 96 或 120 dpi……但随后画出了那个巨人window 到 300 或 600 dpi 的打印页面(无论打印机是什么)。
如果您能告诉我们如何执行这些备选方案,或者如果您能为我们提供一种不同的方式来实现我们的目标,那么我们将不胜感激。
当前代码:
万一重要,我们的表单包含一个 FlowLayoutPanel,将其他较小的 FlowLayoutPanel 放入列中,这些较小的 FlowLayoutPanel 布置单列的 TextBox、RichTextBox、第三方 RichTextEditor、PictureBox 和 DataGridView。我们使用派生自 PrintDocument 的 class 实现 OnBeginPrint、OnPrintPage 和 OnEndPrint。在 OnPrintPage 中,它操纵我们正常的 window 屏幕外(实际屏幕的下方和右侧)以适应页面大小,然后要求我们的主面板(顶部的 FlowLayoutPanel)进行 DrawToBitmap,然后使用传入的 Graphics 对象PrintEventArgs 到DrawImage 即Bitmap。我们还使用 Graphics.DrawString 为每个页面应用页脚。主要代码:
using (Bitmap bm = new Bitmap(sz.Width, sz.Height))
{
Rectangle rect = new Rectangle(0, 0, sz.Width, sz.Height);
mp.DrawToBitmap(bm, rect);
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; // so footer is anti-aliased
e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; // so when we scale up, we smooth out the jaggies somewhat
e.Graphics.DrawImage(bm, this.MarginBounds, rect, GraphicsUnit.Pixel);
if (this.Footer != null)
e.Graphics.DrawImage(this.Footer, this.FooterLocation);
if (!string.IsNullOrEmpty(pageNumber))
{
e.Graphics.DrawString(pageNumber, KBStyle.Normal.Font, Brushes.Black,
this.MarginBounds.X, this.FooterLocation.Y + FooterOffset);
}
}
我们应该怎么做才能使打印页面达到 600dpi? (甚至 300 dpi 也很棒!)
当我们打印这个时,从 120dpi 机器打印出来的效果比从 96dpi 机器打印出来的效果好得多,因此我们知道它是以屏幕分辨率打印的。但也让我们想知道是否有一些简单的方法可以告诉它“这个表单应该以 600 dpi 的分辨率绘制”,然后上面的所有其余代码都可以正常工作。
注意:如果我们抓取一个 EMF(增强型图元文件)并在上面的代码中将其打印到打印机,则该 EMF 以 600dpi 输出。不幸的是,我们还没有找到可以在 FlowLayoutPanel 而不是 DrawToBitmap 上调用的 DrawToEMF 方法。将位图更改为 600dpi 没有帮助...... DrawToBitmap 方法似乎仍然以屏幕分辨率绘制位图。
谢谢!!
这里完全是猜测,但是使用 CSS 呢?我猜你想缩放多少,不知道你怎么知道打印机的比例。
使用印刷媒体查询使它适用于印刷,但不影响屏幕视图。
@media print {
* {
transform: scale(2000px,2000px);
}
}
好的,我已经弄明白了...而且效果很好!
我仍然不知道如何创建 300dpi 的表单并使用自动缩放功能。
但是……
我已经证明,如果您在 96 dpi 下创建比需要大 3.125 倍的 window,并将字体放大 3.125 倍,依此类推,这样一切都是您需要的像素数为 300dpi,即使您的屏幕为 96dpi,那么您可以使用正常的 Control.DrawToBitmap() 功能将其转换为位图,然后您可以使用 GDI Graphics.DrawImage(thatGiantBitmap, giantSrcRect , pageSizeDestRect) 到打印机 Graphics 对象,它会将那些巨大的 96dpi 像素映射到页面大小的 300dpi 像素,为您提供 300dpi 的打印。完美。
对于支持调整大小并让我们的用户任意缩放内容的任何 windows,然后打印所见即所得很容易:
在 PrintDocument 的 OnBeginPrint 中,执行:
(1) 可选地复制表单,以免混淆用户正在查看的内容
(2) 将要打印的表格移到屏幕外(所有屏幕的下方和右侧)
(3) 设置Form允许大于屏幕大小(WinForms默认不会大于屏幕)
(4) 用 300 dpi 除以你的屏幕 dpi 得到增长因子
(5) 按增长因子增长您的表格
(6) 按增长因子缩放其内容(如果它们不自动缩放/自动缩放表单的大小)
在 PrintDocument 的 OnPrintPage 中,执行:
(7) 在您要打印的表单中的任何控件上,对与该控件大小相同的位图执行 DrawToBitmap()
(8) 在 e.Graphics 上执行 DrawImage(thatGiantBitmap, giantSrcRect, pageSizeDestRect)
如果您的 thatGiantBitmap 中有那么多像素,则 DrawImage 调用将以打印机的分辨率绘制。在这种情况下,我计算位图以给出 300 dpi 所需的像素数,因此即使打印机为 600 dpi,我也将获得 300 dpi 的打印输出。如果您需要完整的 600 dpi,只需在步骤 4 的计算中使用 600 dpi。
问题:
我们需要有关如何使用 WinForms 自动缩放到不同 DPI 的能力的帮助,以允许我们以 600dpi 而不是屏幕 DPI 打印表单。
对于所见即所得的打印,我们只是简单地采用我们精心布置的 window 并打印它(关闭滚动条和按钮等)。效果很好,除了一件事:它以 96dpi 或 120dpi 显示(无论屏幕分辨率是多少)……两者都看起来粗糙且不专业(我们的客户抱怨)。尽管它与屏幕上的内容一样可读,但您希望印刷文档比屏幕上的文档更具可读性……您希望能够看到更多详细信息,能够阅读较小的文本等。
考虑的备选方案:
鉴于我们的自动缩放效果很好,因此我们的 window 在 96dpi、120dpi、144 dpi 等分辨率下看起来不错,我们希望我们可以在 600dpi 下绘制 window然后打印出来。
或者,我们着眼于将 window 离屏画得比正常大 5-6 倍,以便我们拥有与 600dpi 相同数量的像素,但分辨率为 96 或 120 dpi……但随后画出了那个巨人window 到 300 或 600 dpi 的打印页面(无论打印机是什么)。
如果您能告诉我们如何执行这些备选方案,或者如果您能为我们提供一种不同的方式来实现我们的目标,那么我们将不胜感激。
当前代码:
万一重要,我们的表单包含一个 FlowLayoutPanel,将其他较小的 FlowLayoutPanel 放入列中,这些较小的 FlowLayoutPanel 布置单列的 TextBox、RichTextBox、第三方 RichTextEditor、PictureBox 和 DataGridView。我们使用派生自 PrintDocument 的 class 实现 OnBeginPrint、OnPrintPage 和 OnEndPrint。在 OnPrintPage 中,它操纵我们正常的 window 屏幕外(实际屏幕的下方和右侧)以适应页面大小,然后要求我们的主面板(顶部的 FlowLayoutPanel)进行 DrawToBitmap,然后使用传入的 Graphics 对象PrintEventArgs 到DrawImage 即Bitmap。我们还使用 Graphics.DrawString 为每个页面应用页脚。主要代码:
using (Bitmap bm = new Bitmap(sz.Width, sz.Height))
{
Rectangle rect = new Rectangle(0, 0, sz.Width, sz.Height);
mp.DrawToBitmap(bm, rect);
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; // so footer is anti-aliased
e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; // so when we scale up, we smooth out the jaggies somewhat
e.Graphics.DrawImage(bm, this.MarginBounds, rect, GraphicsUnit.Pixel);
if (this.Footer != null)
e.Graphics.DrawImage(this.Footer, this.FooterLocation);
if (!string.IsNullOrEmpty(pageNumber))
{
e.Graphics.DrawString(pageNumber, KBStyle.Normal.Font, Brushes.Black,
this.MarginBounds.X, this.FooterLocation.Y + FooterOffset);
}
}
我们应该怎么做才能使打印页面达到 600dpi? (甚至 300 dpi 也很棒!)
当我们打印这个时,从 120dpi 机器打印出来的效果比从 96dpi 机器打印出来的效果好得多,因此我们知道它是以屏幕分辨率打印的。但也让我们想知道是否有一些简单的方法可以告诉它“这个表单应该以 600 dpi 的分辨率绘制”,然后上面的所有其余代码都可以正常工作。
注意:如果我们抓取一个 EMF(增强型图元文件)并在上面的代码中将其打印到打印机,则该 EMF 以 600dpi 输出。不幸的是,我们还没有找到可以在 FlowLayoutPanel 而不是 DrawToBitmap 上调用的 DrawToEMF 方法。将位图更改为 600dpi 没有帮助...... DrawToBitmap 方法似乎仍然以屏幕分辨率绘制位图。
谢谢!!
这里完全是猜测,但是使用 CSS 呢?我猜你想缩放多少,不知道你怎么知道打印机的比例。 使用印刷媒体查询使它适用于印刷,但不影响屏幕视图。
@media print {
* {
transform: scale(2000px,2000px);
}
}
好的,我已经弄明白了...而且效果很好!
我仍然不知道如何创建 300dpi 的表单并使用自动缩放功能。
但是……
我已经证明,如果您在 96 dpi 下创建比需要大 3.125 倍的 window,并将字体放大 3.125 倍,依此类推,这样一切都是您需要的像素数为 300dpi,即使您的屏幕为 96dpi,那么您可以使用正常的 Control.DrawToBitmap() 功能将其转换为位图,然后您可以使用 GDI Graphics.DrawImage(thatGiantBitmap, giantSrcRect , pageSizeDestRect) 到打印机 Graphics 对象,它会将那些巨大的 96dpi 像素映射到页面大小的 300dpi 像素,为您提供 300dpi 的打印。完美。
对于支持调整大小并让我们的用户任意缩放内容的任何 windows,然后打印所见即所得很容易:
在 PrintDocument 的 OnBeginPrint 中,执行:
(1) 可选地复制表单,以免混淆用户正在查看的内容
(2) 将要打印的表格移到屏幕外(所有屏幕的下方和右侧)
(3) 设置Form允许大于屏幕大小(WinForms默认不会大于屏幕)
(4) 用 300 dpi 除以你的屏幕 dpi 得到增长因子
(5) 按增长因子增长您的表格
(6) 按增长因子缩放其内容(如果它们不自动缩放/自动缩放表单的大小)
在 PrintDocument 的 OnPrintPage 中,执行:
(7) 在您要打印的表单中的任何控件上,对与该控件大小相同的位图执行 DrawToBitmap()
(8) 在 e.Graphics 上执行 DrawImage(thatGiantBitmap, giantSrcRect, pageSizeDestRect)
如果您的 thatGiantBitmap 中有那么多像素,则 DrawImage 调用将以打印机的分辨率绘制。在这种情况下,我计算位图以给出 300 dpi 所需的像素数,因此即使打印机为 600 dpi,我也将获得 300 dpi 的打印输出。如果您需要完整的 600 dpi,只需在步骤 4 的计算中使用 600 dpi。