当 DPI 为 150% 时,我的表单无法正确打印
My form is not printing correctly when DPI is 150%
我有一个可以在我的机器上正确打印的表单,但是当我在另一台机器上部署该应用程序时,该表单不适合页面并且桌面背景出现在打印的文档上。两台机器之间的主要区别在于一台机器的 DPI 设置为 150%。我已经多次更改自动缩放,但没有任何变化。该表格在屏幕上看起来不错,但打印不正确。下面是我正在使用的代码。
private void btnPrint_Click(object sender, EventArgs e)
{
CaptureScreen();
printPreviewDialog1.Document = printDocument1;
printPreviewDialog1.ShowDialog();
}
Bitmap memoryImage;
private void CaptureScreen()
{
Graphics myGraphics = this.CreateGraphics();
Size s = this.Size;
memoryImage = new Bitmap(s.Width, s.Height, myGraphics);
Graphics memoryGraphics = Graphics.FromImage(memoryImage);
memoryGraphics.CopyFromScreen(this.Location.X, this.Location.Y, 0, 0, s);
}
private void printDocument1_PrintPage(System.Object sender,
System.Drawing.Printing.PrintPageEventArgs e)
{
e.Graphics.DrawImage(memoryImage, 0, 0);
}
更高的 dpi 缩放比例(如旧的 125% 缩放比例)不是通过增加 Windows 字体大小并让应用程序处理缩放比例来实现的,而是让操作系统为您进行缩放比例。在这种模式下,操作系统向应用程序提供有关实际 dpi 设置的信息,并在绘制其表面时自行缩放应用程序。
结果是在您的应用程序内部,像素位置和大小与屏幕上使用的不是真实的。但是 CopyFromScreen()
方法需要实际的像素坐标和大小。您需要找出您的应用程序经历的像素缩放,然后将此缩放应用于您使用的坐标。
这是工作代码(getScalingFactor()
方法是从 this answer 偷来的)。
[DllImport("gdi32.dll")]
static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
public enum DeviceCap
{
VERTRES = 10,
DESKTOPVERTRES = 117,
}
private float getScalingFactor()
{
using (Graphics g = Graphics.FromHwnd(IntPtr.Zero))
{
IntPtr desktop = g.GetHdc();
try
{
int LogicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.VERTRES);
int PhysicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.DESKTOPVERTRES);
float ScreenScalingFactor = (float)PhysicalScreenHeight / (float)LogicalScreenHeight;
return ScreenScalingFactor;
}
finally
{
g.ReleaseHdc();
}
}
}
private void button1_Click(object sender, EventArgs e)
{
using (Graphics myGraphics = this.CreateGraphics())
{
var factor = getScalingFactor();
Size s = new Size((int)(this.Size.Width * factor), (int)(this.Size.Height * factor));
using (Bitmap memoryImage = new Bitmap(s.Width, s.Height, myGraphics))
{
using (Graphics memoryGraphics = Graphics.FromImage(memoryImage))
{
memoryGraphics.CopyFromScreen((int)(Location.X * factor), (int)(Location.Y * factor), 0, 0, s);
memoryImage.Save(@"D:\x.png", ImageFormat.Png);
}
}
}
}
我有一个可以在我的机器上正确打印的表单,但是当我在另一台机器上部署该应用程序时,该表单不适合页面并且桌面背景出现在打印的文档上。两台机器之间的主要区别在于一台机器的 DPI 设置为 150%。我已经多次更改自动缩放,但没有任何变化。该表格在屏幕上看起来不错,但打印不正确。下面是我正在使用的代码。
private void btnPrint_Click(object sender, EventArgs e)
{
CaptureScreen();
printPreviewDialog1.Document = printDocument1;
printPreviewDialog1.ShowDialog();
}
Bitmap memoryImage;
private void CaptureScreen()
{
Graphics myGraphics = this.CreateGraphics();
Size s = this.Size;
memoryImage = new Bitmap(s.Width, s.Height, myGraphics);
Graphics memoryGraphics = Graphics.FromImage(memoryImage);
memoryGraphics.CopyFromScreen(this.Location.X, this.Location.Y, 0, 0, s);
}
private void printDocument1_PrintPage(System.Object sender,
System.Drawing.Printing.PrintPageEventArgs e)
{
e.Graphics.DrawImage(memoryImage, 0, 0);
}
更高的 dpi 缩放比例(如旧的 125% 缩放比例)不是通过增加 Windows 字体大小并让应用程序处理缩放比例来实现的,而是让操作系统为您进行缩放比例。在这种模式下,操作系统向应用程序提供有关实际 dpi 设置的信息,并在绘制其表面时自行缩放应用程序。
结果是在您的应用程序内部,像素位置和大小与屏幕上使用的不是真实的。但是 CopyFromScreen()
方法需要实际的像素坐标和大小。您需要找出您的应用程序经历的像素缩放,然后将此缩放应用于您使用的坐标。
这是工作代码(getScalingFactor()
方法是从 this answer 偷来的)。
[DllImport("gdi32.dll")]
static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
public enum DeviceCap
{
VERTRES = 10,
DESKTOPVERTRES = 117,
}
private float getScalingFactor()
{
using (Graphics g = Graphics.FromHwnd(IntPtr.Zero))
{
IntPtr desktop = g.GetHdc();
try
{
int LogicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.VERTRES);
int PhysicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.DESKTOPVERTRES);
float ScreenScalingFactor = (float)PhysicalScreenHeight / (float)LogicalScreenHeight;
return ScreenScalingFactor;
}
finally
{
g.ReleaseHdc();
}
}
}
private void button1_Click(object sender, EventArgs e)
{
using (Graphics myGraphics = this.CreateGraphics())
{
var factor = getScalingFactor();
Size s = new Size((int)(this.Size.Width * factor), (int)(this.Size.Height * factor));
using (Bitmap memoryImage = new Bitmap(s.Width, s.Height, myGraphics))
{
using (Graphics memoryGraphics = Graphics.FromImage(memoryImage))
{
memoryGraphics.CopyFromScreen((int)(Location.X * factor), (int)(Location.Y * factor), 0, 0, s);
memoryImage.Save(@"D:\x.png", ImageFormat.Png);
}
}
}
}