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 w
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
PaintEventArgs
has a Graphics
available in its Graphics
property.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)For migration projects we can use built in converstion support functions
microsoft.visualbasic.compatibility.vb6.twipsperpixelx
microsoft.visualbasic.compatibility.vb6.twipsperpixely
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
Old post I know but here is an FYI and some math for the 1440 answers above...
A twip is not simply 1/1440
th 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)
.