Click here to Skip to main content
15,890,527 members
Home / Discussions / C#
   

C#

 
GeneralSetup with InstallShield Pin
quocbao21-May-04 16:34
quocbao21-May-04 16:34 
GeneralRe: Setup with InstallShield Pin
Heath Stewart22-May-04 2:38
protectorHeath Stewart22-May-04 2:38 
GeneralCalling a function in another window. Pin
Bojan Rajkovic21-May-04 16:13
Bojan Rajkovic21-May-04 16:13 
GeneralRe: Calling a function in another window. Pin
Dimitris Iliopoulos22-May-04 0:06
Dimitris Iliopoulos22-May-04 0:06 
GeneralTest and label fields misalign on windows 2000 Pin
Parrish Pope21-May-04 15:58
sussParrish Pope21-May-04 15:58 
GeneralRe: Test and label fields misalign on windows 2000 Pin
Dimitris Iliopoulos22-May-04 0:10
Dimitris Iliopoulos22-May-04 0:10 
GeneralRe: Test and label fields misalign on windows 2000 Pin
Heath Stewart22-May-04 2:47
protectorHeath Stewart22-May-04 2:47 
GeneralRe: Test and label fields misalign on windows 2000 Pin
Heath Stewart22-May-04 3:38
protectorHeath Stewart22-May-04 3:38 
Ignore that last reply. That's not a solution but in the most extreme circumstances.

On laptops - and even some desktops - it's common that the DPI (dots per inch) is set higher. Desktops are typically at 96 DPI while newer laptops (with much better displays capable of higher resolutions) are at 120 DPI. Unfortunately, the .NET Framework uses pixels, a logical unit. VB6, for example, uses twips which are a physical unit (like an inch or a point). See http://visualbasic.about.com/cs/visualbasicfaq/a/dykpixeltwip.htm[^] for more information.

How do you convert this? By P/Invoking GetDeviceCaps and initializing a couple of static properties with the scale factor. You should also handle the Microsoft.Win32.SystemEvents.DisplaySettingChanged event so that you can update these when the display settings change. See How to Write High-DPI Applications[^] in the MSDN Library.

Using those concepts, you could create a class like so:
public sealed class Display
{
  static Display()
  {
    SystemEvents.DisplaySettingsChanged += new EventHandler(Update);
  }
  private Display() {} // Prevent instantiation
 
  [DllImport("gdi32.dll")]
  private static extern IntPtr GetDeviceCaps(IntPtr hdc, IntPtr index);
 
  [DllImport("user32.dll")]
  private static extern IntPtr GetDC(IntPtr hwnd);
 
  [DllImport("user32.dll")]
  private static extern IntPtr ReleaseDC(IntPtr hwnd, IntPtr hdc);
 
  private static void Update()
  {
    Setup(true);
  }
  private static void Setup(bool force)
  {
    if (initialized && !force) return;
    logsPerPixelX  = logsPerPixelY = 0; // Initial values
    IntPtr hdc = GetHDC(IntPtr.Zero);
    try
    {
      if (!hdc.Equals(IntPtr.Zero))
      {
        IntPtr value;
        value = GetDeviceCaps(hdc, 88); // LOGPIXELSX
        logsPerPixelX = 1440 / value.ToInt32();
        value = GetDeviceCaps(hdc, 90); // LOGPIXELSY
        logsPerPixelY = 1440 / value.ToInt32();
        ReleaseDC(IntPtr.Zero, hdc);
      }
    }
    catch {}
    if (logsPerPixelX == 0) logsPerPixelX = 15; // Default for 96 DPI
    if (logsPerPixelY == 0) logsPerPixelY = 15; // Default for 96 DPI
    initialized = true;
  }
  private static bool initialized;
  private static int twipsPerPixelX;
  private static int twipsPerPixelY;
  public static int TwipsPerPixelX
  {
    get
    {
      Setup(false);
      return TwipsPerPixelX;
    }
  }
  public static int TwipsPerPixelY
  {
    get
    {
      Setup(false);
      return TwipsPerPixelY;
    }
  }
  public static int FromPixelsX(int x, ScaleMode mode)
  {
    switch (mode)
    {
      case ScaleMode.Points:
        return PixelsToTwipsX(x) / 20;
      case ScaleMode.Inches:
        return PixelsToTwipsX(x) / 1440;
      default:
        throw new ArgumentException("Invalid scale mode.", "mode");
    }
  }
  public static int FromPixelsY(int y, ScaleMode mode)
  {
    switch (mode)
    {
      case ScaleMode.Points:
        return PixelsToTwipsY(y) / 20;
      case ScaleMode.Inches:
        return PixelsToTwipsY(y) / 1440;
      default:
        throw new ArgumentException("Invalid scale mode.", "mode");
    }
  }
  public static int ToPixelsX(int x, ScaleMode mode)
  {
    switch (mode)
    {
      case ScaleMode.Points:
        return TwipsToPixelsX(x * 20);
      case ScaleMode.Inches:
        return TwipsToPixelsX(x * 1440);
      default:
        throw new ArgumentException("Invalid scale mode.", "mode");
    }
  }
  public static int ToPixelsY(int y, ScaleMode mode)
  {
    switch (mode)
    {
      case ScaleMode.Points:
        return TwipsToPixelsY(y * 20);
      case ScaleMode.Inches:
        return TwipsToPixelsY(y * 1440);
      default:
        throw new ArgumentException("Invalid scale mode.", "mode");
    }
  }
  public static int PixelsToTwipsX(int x)
  {
    Setup(false);
    return x * twipsPerPixelX;
  }
  public static int PixelsToTwipsY(int y)
  {
    Setup(false);
    return y * twipsPerPixelY;
  }
  public static int TwipsToPixelsX(int x)
  {
    Setup(false);
    return x / twipsPerPixelX;
  }
  public static int TwipsToPixelsY(int y)
  {
    Setup(false);
    return y / twipsPerPixelY;
  }
}
 
// A couple of examples
public enum ScaleMode
{
  Points,
  Inches
}
This is similar to code I developed for our application, based on the Type Microsoft.VisualBasic.Compatibility.VB6.Support, Microsoft.VisualBasic.Compatibility. You can use this to convert pixels to physical units more suitable for different display resolutions.

 

Microsoft MVP, Visual C#
My Articles
GeneralRe: Test and label fields misalign on windows 2000 Pin
Dimitris Iliopoulos23-May-04 3:46
Dimitris Iliopoulos23-May-04 3:46 
GeneralRe: Test and label fields misalign on windows 2000 Pin
Heath Stewart23-May-04 3:49
protectorHeath Stewart23-May-04 3:49 
GeneralRe: Test and label fields misalign on windows 2000 Pin
Parrish23-May-04 7:17
Parrish23-May-04 7:17 
GeneralRe: Test and label fields misalign on windows 2000 Pin
Heath Stewart23-May-04 7:43
protectorHeath Stewart23-May-04 7:43 
Generalabout one Process, multi AppDomain Design Pin
pig123421-May-04 14:52
pig123421-May-04 14:52 
GeneralRe: about one Process, multi AppDomain Design Pin
Heath Stewart22-May-04 2:45
protectorHeath Stewart22-May-04 2:45 
GeneralPrinting a .pdf Pin
TigerNinja_21-May-04 11:55
TigerNinja_21-May-04 11:55 
GeneralRe: Printing a .pdf Pin
Dave Kreskowiak21-May-04 12:24
mveDave Kreskowiak21-May-04 12:24 
GeneralVolume Control Pin
kratchkov21-May-04 10:15
kratchkov21-May-04 10:15 
QuestionHow Can I Unload an Assembly? Pin
goodpilot21-May-04 10:15
goodpilot21-May-04 10:15 
AnswerRe: How Can I Unload an Assembly? Pin
Heath Stewart21-May-04 10:49
protectorHeath Stewart21-May-04 10:49 
AnswerRe: How Can I Unload an Assembly? Pin
Marc Clifton22-May-04 14:58
mvaMarc Clifton22-May-04 14:58 
GeneralRe: How Can I Unload an Assembly? Pin
goodpilot26-May-04 3:17
goodpilot26-May-04 3:17 
GeneralOverloading Pin
Gary Kirkham21-May-04 9:39
Gary Kirkham21-May-04 9:39 
GeneralRe: Overloading Pin
Heath Stewart21-May-04 9:56
protectorHeath Stewart21-May-04 9:56 
GeneralRe: Overloading Pin
Gary Kirkham21-May-04 10:07
Gary Kirkham21-May-04 10:07 
GeneralRe: Overloading Pin
Heath Stewart21-May-04 10:12
protectorHeath Stewart21-May-04 10:12 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.