简体   繁体   English

以比屏幕分辨率更高的dpi打印表单

[英]Print a Form at higher dpi than screen resolution

Problem: 问题:

We need help with how to use WinForms' ability to auto-scale to different DPI's to allow us to print our Forms at 600dpi, rather than at the screen DPI. 我们需要有关如何使用WinForms自动缩放到不同DPI的功能的帮助,以允许我们以600dpi而不是屏幕DPI的格式打印表单。

For What-You-See-Is-What-You-Get printing, we have been simply taking our nicely laid out window and printing it (turning off scrollbars and buttons and such). 对于您看到的就是您得到的打印,我们只是简单地将布局精美的窗口打印出来(关闭滚动条和按钮等)。 That works great EXCEPT for one thing: it comes out at 96dpi or 120dpi (whatever is the screen resolution)… either of which look grainy and unprofessional (our customers are complaining). 除了一件事,它的效果非常好:它的输出速度为96dpi或120dpi(无论屏幕分辨率是什么)……两者看上去都不真实且不专业(我们的客户在抱怨)。 And although it is as readable as what would be on the screen, you expect printed documents to be MORE readable than on-screen… you expect to be able to see additional details, to be able to read smaller text, etc. 而且,尽管它与屏幕上的内容一样可读,但是您希望打印的文档比在屏幕上更具可读性……您希望能够看到更多详细信息,能够阅读更小的文本,等等。

Alternatives considered: 考虑的替代方案:

Given we have auto-scaling working great, such that our window looks good in 96dpi, 120dpi, 144 dpi, etc., we were hoping we could just draw our window at 600dpi and then print that. 鉴于我们具有很好的自动缩放功能,因此我们的窗口在96dpi,120dpi,144 dpi等条件下看起来都不错,我们希望我们可以以600dpi的速度绘制窗口然后进行打印。

OR, we looked at drawing the window off-screen 5-6x larger than normal such that we have the same number of pixels as 600dpi, but at 96 or 120 dpi… but then drawing that giant window to the printed page at 300 or 600 dpi (whatever the printer is). 或者,我们看着在屏幕外以比正常大5-6倍的比例绘制窗口,以使我们拥有与600dpi相同的像素数,但像素为96或120 dpi…但是随后以300或600的比例将巨大的窗口绘制到打印页面dpi(无论打印机是什么)。

If you can tell us how to do either of those alternatives, OR if you can give us a different way to accomplish our goal, then we would greatly appreciate it. 如果您可以告诉我们如何执行这些替代方法之一,或者可以给我们提供实现目标的其他方法,那么我们将不胜感激。

Current code: 当前代码:

In case it matters, our Form consists of a FlowLayoutPanel laying other smaller FlowLayoutPanels into columns, those smaller FlowLayoutPanels laying out a single column of TextBoxes, RichTextBoxes, a third-party RichTextEditor, PictureBoxes, and DataGridViews. 如果需要的话,我们的窗体由将其他较小的FlowLayoutPanels放置到列中的FlowLayoutPanel组成,那些较小的FlowLayoutPanels布局了TextBoxes,RichTextBoxes,第三方RichTextEditor,PictureBoxes和DataGridViews的单个列。 We use a class derived from PrintDocument implementing OnBeginPrint, OnPrintPage, and OnEndPrint. 我们使用从PrintDocument派生的类来实现OnBeginPrint,OnPrintPage和OnEndPrint。 In OnPrintPage, it manipulates our normal window off-screen (below and right of the actual screens) to fit the page size, then asks our main panel (the top FlowLayoutPanel) to DrawToBitmap, then uses the Graphics object passed into the PrintEventArgs to DrawImage that Bitmap. 在OnPrintPage中,它操纵正常的屏幕外窗口(在实际屏幕的下方和右侧)以适合页面大小,然后要求主面板(顶部FlowLayoutPanel)使用DrawToBitmap,然后使用传递到PrintEventArgs中的Graphics对象到DrawImage该位图。 We also use Graphics.DrawString to apply a footer to each page. 我们还使用Graphics.DrawString将页脚应用于每个页面。 The main code: 主要代码:

                    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);
                        }
                    }

How should we do this to get 600dpi to the printed page? 如何使打印的页面达到600dpi? (Or even 300 dpi would be great!) (甚至300 dpi都很棒!)

When we print this, it looks far better when printed from a 120dpi machine than when printed from a 96dpi machine, hence why we know it is printing at screen resolution. 当我们打印时,从120dpi的机器打印时看起来比从96dpi的机器打印时看起来要好得多,因此为什么我们知道它是以屏幕分辨率打印的。 But also makes us wonder if there's some simple way to tell it “this Form should draw at 600 dpi” and then all the rest of the code above just works. 但是,这也让我们怀疑是否有某种简单的方法可以告诉它“此表格应以600 dpi的速度绘制”,然后上面的所有其余代码都可以正常工作。

Note: if we grab an EMF (Enhanced Metafile) and print it to the printer in the code above, that EMF comes out at 600dpi. 注意:如果我们使用上面的代码抓取EMF(增强型图元文件)并将其打印到打印机,则该EMF的输出速度为600dpi。 Unfortunately, we haven't found a DrawToEMF method that we can call on the FlowLayoutPanel instead of DrawToBitmap. 不幸的是,我们没有找到可以在FlowLayoutPanel而不是DrawToBitmap上调用的DrawToEMF方法。 Changing the Bitmap to be 600dpi doesn't help… the DrawToBitmap method still seems to draw the bitmap at screen resolution. 将位图更改为600dpi并没有帮助……DrawToBitmap方法似乎仍然以屏幕分辨率绘制位图。

Thanks!! 谢谢!!

Okay, I have figured this out... and it works great! 好的,我已经弄清楚了...而且效果很好!

I still don't know how to create a form at 300dpi and use the auto-scaling functionality. 我仍然不知道如何以300dpi的速度创建表单并使用自动缩放功能。

BUT… 但…

I have proven that if you create the window 3.125x larger than needed at 96 dpi, and scale the font up 3.125x, and so on, such that everything is the pixel count you'd need to be at 300dpi, even though your screen is at 96dpi, then you can use the normal Control.DrawToBitmap() functionality to turn that into a Bitmap, and then you can use the GDI Graphics.DrawImage(thatGiantBitmap, giantSrcRect, pageSizeDestRect) to the printer Graphics object, and it will map those giant 96dpi pixels to the page-size 300dpi pixels, giving you a 300dpi print. 我已经证明,如果您创建的窗口比96 dpi时所需的窗口大3.125倍,并且将字体放大至3.125倍,依此类推,那么即使您的屏幕是像素数,也需要300 dpi的速度为96dpi,则可以使用正常的Control.DrawToBitmap()功能将其转换为位图,然后可以使用GDI Graphics.DrawImage(thatGiantBitmap,giantSrcRect,pageSizeDestRect)到打印机Graphics对象,它将进行映射那些巨大的96dpi像素到页面大小的300dpi像素,可为您提供300dpi的打印效果。 Perfect. 完善。

For any of our windows that support resizing AND let our users zoom the contents arbitrarily, then printing What-You-See-Is-What-You-Get is easy: 对于我们支持缩放大小并允许用户任意缩放内容的任何窗口,然后轻松打印“您所见即所得”即可:

In OnBeginPrint of your PrintDocument, do: 在您的PrintDocument的OnBeginPrint中,执行以下操作:

(1) Optionally dup the Form so as to not mess with what the user is looking at (1)(可选)将表单重复放置,以免与用户的查看内容混淆

(2) Move the Form you want to print off-screen (below and right of all your screens) (2)将您要打印的表格移出屏幕(在所有屏幕的下方和右侧)

(3) Set the Form so that it is allowed to grow bigger than the screen size (by default WinForms won't grow larger than the screen) (3)设置窗体,使其可以大于屏幕尺寸(默认情况下,WinForms不会大于屏幕尺寸)

(4) Divide 300 dpi by your screen dpi to get the growth factor (4)将300 dpi除以屏幕dpi以获得增长因子

(5) Grow your Form by growth factor (5)通过成长因素发展自己的形态

(6) Zoom its contents by growth factor (if they don't auto-scale / auto-zoom with the Form's size) (6)按增长因子缩放其内容(如果它们没有根据窗体的大小自动缩放/自动缩放)

In OnPrintPage of your PrintDocument, do: 在你的PrintDocument的OnPrintPage,这样做:

(7) On whatever Control in your Form you want to print, do DrawToBitmap() to a Bitmap the size of that Control (7)在要打印的窗体中的任何控件上,将DrawToBitmap()设置为该控件大小的位图

(8) On the e.Graphics do DrawImage(thatGiantBitmap, giantSrcRect, pageSizeDestRect) (8)在e.Graphics上执行DrawImage(thatGiantBitmap,giantSrcRect,pageSizeDestRect)

That DrawImage call will draw at the printer's resolution, if you have that many pixels in your thatGiantBitmap. 如果您的thatGiantBitmap中有那么多像素,则该DrawImage调用将以打印机的分辨率进行绘制。 In this case, I computed the Bitmap to give the number of pixels needed for 300 dpi, so I will get 300 dpi print-outs even if the printer is 600 dpi. 在这种情况下,我计算了位图以给出300 dpi所需的像素数,因此即使打印机为600 dpi,我也将获得300 dpi的打印输出。 If you need full 600 dpi, just use 600 dpi in step 4's calculation. 如果需要完整的600 dpi,只需在第4步的计算中使用600 dpi。

Total guess here, but what about using CSS? 完全可以猜到,但是使用CSS呢? I'm guessing at how much you want to scale, and don't know how you would know what scale the printer is. 我正在猜测您要缩放多少,并且不知道如何知道打印机的缩放比例。 Using the print media query makes this work for print but leaves the screen view alone. 使用打印介质查询使此功能适用于打印,但仅保留屏幕视图。

@media print {
  * {
    transform: scale(2000px,2000px);
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM