How do I convert Twips to Pixels in .NET?
Asked Answered
D

4

25

I'm working on a migration project in which a database actually stores display sizes in twips. Since I can't use twips to assign sizes to WPF or Winforms controls, I was wondering if .NET has a conversion method usable at runtime?

Derman answered 28/10, 2010 at 15:27 Comment(1)
unitconverters.net/typography/twip-to-pixel-x.htm says 1 Pixel = 15 twips ==> 1 twips = 1/15 pxCowpuncher
D
30

It turns out that the migration tool has something, but it wouldn't do any good at runtime. Here's what I did (if the hard-coded value in the extension method were changed to the value for points per inch it would work as a point converter too):

1 Twip = 1/1440th of an inch. The .NET Graphics object has a method DpiX and DpiY which can be used to determine how many pixels are in an inch. Using those measurements I created the following extension methods for Graphics:

using System.Drawing;

static class Extensions
{
    /// <summary>
    /// Converts an integer value in twips to the corresponding integer value
    /// in pixels on the x-axis.
    /// </summary>
    /// <param name="source">The Graphics context to use</param>
    /// <param name="inTwips">The number of twips to be converted</param>
    /// <returns>The number of pixels in that many twips</returns>
    public static int ConvertTwipsToXPixels(this Graphics source, int twips)
    {
        return (int)(((double)twips) * (1.0 / 1440.0) * source.DpiX);
    }

    /// <summary>
    /// Converts an integer value in twips to the corresponding integer value
    /// in pixels on the y-axis.
    /// </summary>
    /// <param name="source">The Graphics context to use</param>
    /// <param name="inTwips">The number of twips to be converted</param>
    /// <returns>The number of pixels in that many twips</returns>
    public static int ConvertTwipsToYPixels(this Graphics source, int twips)
    {
        return (int)(((double)twips) * (1.0 / 1440.0) * source.DpiY);
    }
}

To use these methods one simply has to do the following (assuming you're in a context where CreateGraphics returns a Drawing.Graphics object (here this is a Form, so CreateGraphics is inherited from Form's super-class Control):

using( Graphics g = CreateGraphics() )
{
    Width = g.ConvertTwipsToXPixels(sizeInTwips);
    Height = g.ConvertTwipsToYPixels(sizeInTwips);
}

See the "Remarks" section in the Graphics Class documentation for a list of ways to obtain a graphics object. More complete documentation is available in the tutorial How to: Create Graphics Objects.

Brief summary of easiest ways:

  • Control.CreateGraphics
  • a Paint event's PaintEventArgs has a Graphics available in its Graphics property.
  • Hand Graphics.FromImage an image and it will return a Graphics object that can draw on that image. (NOTE: It is unlikely that you'll want to use twips for an actual image)
Derman answered 28/10, 2010 at 15:28 Comment(3)
got a small error in your code. In the ConvertTwipsToYPixles, you have it using the DipX instead of the DpiYAdvocate
thanks, I have another question. You said that CreateGraphics returns a Drawing.Graphics object. What kind of Graphics it returns? Could you give an example of CreateGraphics method please?Napoleonnapoleonic
CreateGraphics is a member of Control. See the documentation. Graphics is an abstract sealed class that encapsulates drawing to the screen. You don't need to know anything about it if you're using this. Just use any control (Form, Button, etc.) and call it on that. If your class inherits from Control you can use it like I did (with the implied this).Derman
E
6

For migration projects we can use built in converstion support functions

microsoft.visualbasic.compatibility.vb6.twipsperpixelx
microsoft.visualbasic.compatibility.vb6.twipsperpixely
Eliga answered 15/7, 2012 at 4:35 Comment(0)
P
4

For reference, another C# version, using the Win32 API instead of requiring a Graphics objects:

using System.Runtime.InteropServices;

static class SomeUtils {

  public static int ConvertTwipsToPixels(int twips, MeasureDirection direction) {
    return (int)(((double)twips)*((double)GetPixperinch(direction))/1440.0);
  }

  public static int ConvertPixelsToTwips(int pixels, MeasureDirection direction) {
    return (int)((((double)pixels)*1440.0)/((double)GetPixperinch(direction)));
  }

  public static int GetPPI(MeasureDirection direction) {
    int ppi;
    IntPtr dc = GetDC(IntPtr.Zero);

    if (direction == MeasureDirection.Horizontal)
      ppi = GetDeviceCaps(dc, 88); //DEVICECAP LOGPIXELSX
    else
      ppi = GetDeviceCaps(dc, 90); //DEVICECAP LOGPIXELSY

    ReleaseDC(IntPtr.Zero, dc);
    return ppi;
  }

  [DllImport("user32.dll")]
  static extern IntPtr GetDC(IntPtr hWnd);

  [DllImport("user32.dll")]
  static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDC);

  [DllImport("gdi32.dll")]
  static extern int GetDeviceCaps(IntPtr hdc, int devCap);
}

public enum MeasureDirection {
  Horizontal,
  Vertical
}

The MeasureDirection is supposed to be specified as there is no guarantee that pixels are always square (according to the kb).

Reference: kb210590: ACC2000: How to Convert Twips to Pixels

Psia answered 14/12, 2010 at 3:58 Comment(0)
D
2

Old post I know but here is an FYI and some math for the 1440 answers above...

A twip is not simply 1/1440th of an inch. A twip is 1/20 of a point.

The point you are working with in a printable document, typically, is a postscript 72dpi:

72dpi * 20Twips/Point = 1440twips.

So in dealing with say a Crystal report, with a twips width of 15840 (and margins of 0 twips), the width would be 11 inches (15840 / (72 * 20)).

Based on a screen density of 96 dpi, the report will post to the screen at:

1056px wide (96dpi * 11in = 1056px).

Disgusting answered 21/3, 2014 at 18:9 Comment(1)
just for all your information who are using Infragistics One inch is equal to 1,440 twips (twentieths of a desktop point). One inch is equal to 72 desktop points. Source : help.infragistics.com/Help/Doc/WinForms/2016.1/CLR4.0/html/…Cowpuncher

© 2022 - 2024 — McMap. All rights reserved.