DPI图形屏幕分辨率像素WinForm PrintPageEventArgs

5

在我的应用程序运行的任何显示器上,Dpi点与像素有什么关系?

int points;
Screen primary;

public Form1() {
  InitializeComponent();
  points = -1;
  primary = null;
}

void OnPaint(object sender, PaintEventArgs e) {
  if (points < 0) {
    points = (int)(e.Graphics.DpiX / 72.0F); // There are 72 points per inch
  }
  if (primary == null) {
    primary = Screen.PrimaryScreen;
    Console.WriteLine(primary.WorkingArea.Height);
    Console.WriteLine(primary.WorkingArea.Width);
    Console.WriteLine(primary.BitsPerPixel);
  }
}

我现在是否拥有所有所需信息?

我可以使用上述任何信息来找出1200像素有多长吗?


注意:一旦我学会了如何在全球范围内显示我的表单,该表单上的数据将被发送到打印机 - 因此标题中有“PrintPageEventArgs”。 - user153923
3个回答

3

DPI字面上的意思是“每英寸点数”- 其中点等于像素。因此,要确定1200个像素有多长:

int inchesLong = (1200 / e.Graphics.DpiX);

视频 DPI 设置从来都不准确。它们固定为 96、120 或 144,无论显示器尺寸如何。 - Hans Passant
@Hans 不是这样的。例如,我已经在192DPI下测试了我的应用程序。它看起来相当奇特,但缩放得很好! - David Heffernan
@David - 你买了另一个显示屏来与那个 DPI 设置匹配吗?这是必需的,才能得到相同的英寸测量。 - Hans Passant
@Hans 我将我的应用程序设置为 DPIAWARE,然后我认为我至少应该进行一些压力测试!不幸的是,你无法购买具有足够像素的面板来使该 DPI 设置可行,但如果可以的话,它看起来会很棒。而且我已经准备好了! - David Heffernan

2

我知道已经过了几个月,但是在阅读一本关于WPF的书时,我找到了答案:

如果使用标准的Windows DPI设置(96 dpi),每个设备无关单位对应一个真实的物理像素。

[Physical Unit Size] = [Device-Independent Unit Size] x [System DPI]
                     = 1/96 inch x 96 dpi
                     = 1 pixel

因此,在Windows系统的DPI设置中,需要96个像素才能组成一英寸。
但是,这实际上取决于您的显示器尺寸。
对于一个19英寸的LCD显示器,设置分辨率为1600 x 1200,使用勾股定理可以帮助计算显示器的像素密度:
[Screen DPI] = Math.Sqrt(Math.Pow(1600, 2) + Math.Pow(1200, 2)) / 19

利用这些数据,我编写了一个小型的静态工具,并将其保存在我所有项目的工具类中:

/// <summary>
/// Calculates the Screen Dots Per Inch of a Display Monitor
/// </summary>
/// <param name="monitorSize">Size, in inches</param>
/// <param name="resolutionWidth">width resolution, in pixels</param>
/// <param name="resolutionHeight">height resolution, in pixels</param>
/// <returns>double presision value indicating the Screen Dots Per Inch</returns>
public static double ScreenDPI(int monitorSize, int resolutionWidth, int resolutionHeight) {
  //int resolutionWidth = 1600;
  //int resolutionHeight = 1200;
  //int monitorSize = 19;
  if (0 < monitorSize) {
    double screenDpi = Math.Sqrt(Math.Pow(resolutionWidth, 2) + Math.Pow(resolutionHeight, 2)) / monitorSize;
    return screenDpi;
  }
  return 0;
}

我希望其他人能从这个小巧实用的工具中受益。


1

对于屏幕:像素 = Graphics.DpiY * points / 72

对于打印机,提到了您问题主题中的映射,默认情况下1个“像素”等于0.010英寸。这非常接近默认视频dpi为96像素每英寸,使纸张上的复制品与您在监视器上看到的大小相同。

截取表单的屏幕截图并打印它们是一个坏主意。打印机具有更高的分辨率,典型值为600 dpi。打印出来的效果会很粗糙,因为屏幕上的每个像素都会变成纸上的6x6斑点。特别是反锯齿文本,效果非常明显和丑陋。


实际上,该表单只是在将数据发送到打印机之前呈现数据的“打印预览”。该项目应将所有数据绘制到表单上,就像将要发送到打印机一样。清楚吗? :) - user153923
但是,哪个先出现,鸡还是蛋?哈哈 - 在我使用 MS 的 PrintPreviewDialog 之前,我必须将对象绘制为某些东西...除非我漏掉了什么。 - user153923
嗯,最终你想要打印它。一旦你得到了它,你就可以免费预览。反过来做是浪费时间。实现PrintDocument.PrintPage事件处理程序。 - Hans Passant
那么,在这种情况下,我将不得不创建一个自定义的PrintPreview。我的当前绘制事件将向表单上的面板发送信息。还将有添加和删除按钮,以将更多“对象”包括在要打印的列表中。 - user153923
你可以使用设备上下文(System.Drawing.Graphics)进行绘图。在Paint事件处理程序或OnPaint重写中,通过调用BeginPaint获取DC,这是一个“屏幕DC”。当你打印时,会提供一个“打印DC”。当使用PrintDialog或PrintPreviewDialog时,你需要提供一个PrintDocument对象。在该文档的PrintPage事件中,你可以获取一个“打印DC”来进行绘图。 - Tergiver

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接