Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

My form is not printing correctly when DPI is 150%

Tags:

c#

winforms

scale

I have a form that prints correctly on my machine but when I deploy the application on another machine, the form does not fit on the page and the desktop background appears on the printed document. The primary differences between the two machines is that one has the DPI setting at 150%. I have changed auto scaling many times but nothing changes. The form looks ok on screen but just does not print correctly. Below is the code I am using.

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);
    }
like image 763
wsb Avatar asked Mar 29 '16 20:03

wsb


People also ask

Is 150 DPI good enough for print?

For print, 150dpi is considered low-quality printing, even though 72dpi is considered the standard for the web (which is why it's not easy printing quality images straight from the web). Low-resolution images will have blurring and pixelation after printing.

How much DPI do I need for printing?

For printing, the recommended resolution for all images and art files is 300 dpi. The offset press cannot accurately reproduce resolutions above 300, so it is the industry standard.

What does DPI mean in printing?

The terms Dots Per Inch (DPI) and Pixels Per Inch (PPI) are commonly used interchangeably to describe the resolution of an image.


1 Answers

The higher dpi scaling is not (like the old 125% scaling) made by increasing the Windows font size and having the application handle the scaling, but by having the operating system do the scaling for you. In this mode, the operating system lies to the application about the actual dpi settings and does by itself scale the application when drawing its surface.

The result is that inside your application, the pixel positions and sizes are not the real ones used on the screen. But the CopyFromScreen() method requires the actual pixel coordinates and sizes. You need to find out the pixel scaling your application undergoes and then apply this scaling to the coordinates you use.

Here is the working code (The getScalingFactor() method was stolen from 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);
            }
        }
    }
}
like image 95
NineBerry Avatar answered Oct 29 '22 03:10

NineBerry