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?
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 aGraphics
available in itsGraphics
property. - Hand
Graphics.FromImage
an image and it will return aGraphics
object that can draw on that image. (NOTE: It is unlikely that you'll want to use twips for an actual image)
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 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)
.
© 2022 - 2024 — McMap. All rights reserved.