Checking for Screen Rotation Support in NetCF version 2

A couple of months ago, I showed an example of how to P/Invoke to check if your device supports device rotation using version 1 of the .NET Compact Framework.  In that post, I promised to revisit the example for NetCF v2 once Beta 2 was released.

You may recall that in the previous version of this example, we were required, in our DeviceMode structure, to expand each of the DEVMODE structure's char arrays into 32 individual fields.  This is no longer required on NetCF v2 thanks to its expanded marshaling support.

Instead of the individual char fields, the revised DeviceMode structure contains two String objects (DeviceName and FormName).  These Strings are decorated with the MarshalAs attribute which specifies that they are to become char arrays of 32 elements.  This makes accessing these fields much more pleasant as we no longer need to assemble to and disassemble from individual characters.

Note: The following code example was built and tested using the Beta 2 releases of Visual Studio 2005 and .NET Compact Framework version 2.

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

class ScreenRotationCheckNetCFv2
{
    public static void Main()
    {
        String msg;
        Boolean rotationSupported = false;

        // prepare the DeviceMode structure
        DeviceMode devMode = new DeviceMode();
        devMode.Size = (Int16)Marshal.SizeOf(devMode);
        devMode.Fields = DisplayQueryOrientation;
      
        // ask the operating system if it supports screen rotation
        Int32 result = ChangeDisplaySettingsEx(null,        // primary display
                                             ref devMode,
                                             IntPtr.Zero,   // reserved must be 0
                                             ChangeDisplaySettingsTest,
                                             IntPtr.Zero);
        if(0 == result)
        {
            // ChangeDisplaySettingsEx call succeeded,
            //  we can check the results of our query
           
            // non-zero value in DisplayOrientation means
            //  rotation is supported
            if(0 != devMode.DisplayOrientation)
            {
                rotationSupported = true;
            }
           
            // format the message to display
            msg = String.Format("Screen rotation supported: {0}",
                                rotationSupported);
        }
        else
        {
            msg = String.Format("ChangeDisplaySettingsEx failed with error code: {0}",
                                result);
        }

        // display our findings
        MessageBox.Show(msg, "Screen rotation check");
    }   

    // DeviceMode field value(s)
    private static Int32 DisplayQueryOrientation = 0x01000000;

    // ChangeDisplaySettingsEx flags value(s)
    private static Int32 ChangeDisplaySettingsTest = 2;

    // pinvoke(s)
    [DllImport("coredll.dll", SetLastError=true)]
    private extern static Int32 ChangeDisplaySettingsEx(String deviceName,
                                                    ref DeviceMode deviceMode,
                                                    IntPtr hwnd,
                                                    Int32 flags,
                                                    IntPtr param);
}

// managed version of the DEVMODE structure
struct DeviceMode
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]
    public String DeviceName;

    public Int16 SpecVersion;
    public Int16 DriverVersion;
    public Int16 Size;
    public Int16 DriverExtra;
    public Int32 Fields;
    public Int16 Orientation;
    public Int16 PaperSize;
    public Int16 PaperLength;
    public Int16 PaperWidth;
    public Int16 Scale;
    public Int16 Copies;
    public Int16 DefaultSource;
    public Int16 PrintQuality;
    public Int16 Color;
    public Int16 Duplex;
    public Int16 YResolution;
    public Int16 TTOption;
    public Int16 Collate;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]
    public String FormName;

    public Int16 LogPixels;
    public Int32 BitsPerPel;
    public Int32 PelsWidth;
    public Int32 PelsHeight;
    public Int32 DisplayFlags;
    public Int32 DisplayFrequency;
    public Int32 DisplayOrientation;
}

As you can see from the above, the code is much easier to read than the previous version and there is much less of a chance of making structure conversion errors (too many or too few elements).

Enjoy!
-- DK

Disclaimer(s):
This posting is provided "AS IS" with no warranties, and confers no rights.
Some of the information contained within this post may be in relation to beta software. Any and all details are subject to change.