How do I convert Twips to Pixels in .NET?

前端 未结 4 1748
渐次进展
渐次进展 2020-12-09 03:12

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

相关标签:
4条回答
  • 2020-12-09 03:18

    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)
    0 讨论(0)
  • 2020-12-09 03:18

    For migration projects we can use built in converstion support functions

    microsoft.visualbasic.compatibility.vb6.twipsperpixelx
    microsoft.visualbasic.compatibility.vb6.twipsperpixely
    
    0 讨论(0)
  • 2020-12-09 03:20

    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

    0 讨论(0)
  • 2020-12-09 03:27

    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).

    0 讨论(0)
提交回复
热议问题