In my last work project I was in need to change display orientation of Windows Mobile device. Users can do it from settings menu but how to do it from code, especially managed code. There is a good MSDN article covering screen rotation. I can recommend everyone to read it for better understanding of the principles. Everything is about the ChangeDisplaySettingsEx API function that is changing screen orientation and other GDI functionality. One of the arguments passed to the method is the DEVMODE structure with many interesting fields. The most interesting one is the dmDisplayOrientation. It can be used as input when setting the orientation as well as output when asking for current display orientation. Now nothing can stop me to put it in managed code and rotate display like this:

DisplayOrientation.Orientation supported = DisplayOrientation.GetSupportedOrientation();
DisplayOrientation.Orientation actual = DisplayOrientation.GetOrientation();

// Show actual screen rotation
label1.Text = "Actual rotation: " + actual.ToString();

// Test whether display rotation is supported
if (supported == DisplayOrientation.Orientation.DO0)
    label2.Text = "Screen rotation is not supported";
else
{
    label2.Text = "Supported rotations: " + supported.ToString();

    // Rotate the screen
    DisplayOrientation.SetOrientation(DisplayOrientation.Orientation.DO180);
}

Change screen orientation from C

The DisplayOrientation is quite short C# wrapper around the ChangeDisplaySettingsEx. There is a private method named DisplaySettings, which calls the ChangeDisplaySettingsEx with specific flags, whether the get or set of display orientation is required. When the CDS_TEST is passed as a flag, then the get operation is performed. CDS_RESET stands for set operation.

DisplayOrientation contains public method GetSupportedOrientation, which returns all supported display orientations. When only the DisplayOrientation.Orientation.DO0 is returned, it means that screen rotation is not supported. GetOrientation method returns current display orientation. When screen rotation is supported then the SetOrientation can be used.

/// <summary>
/// Provides basic operations for screen rotation
/// </summary>
public static class DisplayOrientation
{
    [Flags]
    public enum Orientation { DO0 = 0, DO90 = 1, DO180 = 2, DO270 = 4 }

    /// <summary>
    /// Returns current screen orientation.
    /// </summary>
    /// <returns>rotation</returns>
    public static Orientation GetOrientation()
    {
        int dmDisplayOrientation = 0;
        if (!DisplaySettings(DM_DISPLAYORIENTATION, 
                             CDS_TEST,
                             ref dmDisplayOrientation))
            throw new Exception("Unexpected exception");

        return (Orientation)dmDisplayOrientation;
    }

    /// <summary>
    /// Rotates screen to given angle
    /// </summary>
    /// <param name="rotationAngle">Display orientation</param>
    public static void SetOrientation(Orientation displayOrientation)
    {
        int dmDisplayOrientation = (int)displayOrientation;
        if (!DisplaySettings(DM_DISPLAYORIENTATION,
                             CDS_RESET,
                             ref dmDisplayOrientation))
            throw new Exception("Rotation not supported");
    }

    /// <summary>
    /// Returns all supported screen orientations.
    /// If only RotationAngle.D0 is returned, device has
    /// no support for screen rotation.
    /// </summary>
    /// <returns>Supported screen orienation</returns>
    public static Orientation GetSupportedOrientation()
    {
        int dmDisplayOrientation = 0;
        if (!DisplaySettings(DM_DISPLAYQUERYORIENTATION, 
                             CDS_TEST,
                             ref dmDisplayOrientation))
            throw new Exception("Unexpected exception");

        return (Orientation)dmDisplayOrientation;
    }

    /// <summary>
    /// P/Invokes the ChangeDisplaySettingsEx with given parameters
    /// </summary>
    /// <param name="devModeFields">fields for DEVMODE</param>
    /// <param name="cdsFlags">CDS flags</param>
    /// <param name="displayOrientation">get/set display orientation</param>
    /// <returns>true if succeded</returns>
    private static bool DisplaySettings(Int32 devModeFields, 
                                        Int32 cdsFlags, 
                                        ref int displayOrientation)
    {               
        // Init DEVMODE structure
        DEVMODE devMode = new DEVMODE();
        devMode.dmSize = (Int16)Marshal.SizeOf(devMode);
        devMode.dmFields = devModeFields;
        devMode.dmDisplayOrientation = displayOrientation;

        // P/Invoke ChangeDisplaySettingsEx
        int result = ChangeDisplaySettingsEx(null,       
                                             ref devMode,
                                             IntPtr.Zero,
                                             cdsFlags,
                                             IntPtr.Zero);
        displayOrientation = devMode.dmDisplayOrientation;

        return (result == 0);
    }

    // Fields constats
    private const Int32 DM_DISPLAYQUERYORIENTATION = 0x01000000;
    private const Int32 DM_DISPLAYORIENTATION = 0x00800000;
    
    // Flags constants
    private const Int32 CDS_TEST = 2;
    private const Int32 CDS_RESET = 0x40000000;

    // P/Invoke
    [DllImport("coredll.dll", SetLastError = true)]
    private extern static Int32 ChangeDisplaySettingsEx(string deviceName,
                                                        ref DEVMODE deviceMode,
                                                        IntPtr hwnd,
                                                        Int32 flags,
                                                        IntPtr param);

    /// <summary>
    /// DEVMODE mannaged code representation
    /// </summary>
    internal struct DEVMODE
    {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string dmDeviceName;
        public Int16 dmSpecVersion;
        public Int16 dmDriverVersion;
        public Int16 dmSize;
        public Int16 dmDriverExtra;
        public Int32 dmFields;
        public Int16 dmOrientation;
        public Int16 dmPaperSize;
        public Int16 dmPaperLength;
        public Int16 dmPaperWidth;
        public Int16 dmScale;
        public Int16 dmCopies;
        public Int16 dmDefaultSource;
        public Int16 dmPrintQuality;
        public Int16 dmColor;
        public Int16 dmDuplex;
        public Int16 dmYResolution;
        public Int16 dmTTOption;
        public Int16 dmCollate;

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string dmFormName;
        public Int16 dmLogPixels;
        public Int32 dmBitsPerPel;
        public Int32 dmPelsWidth;
        public Int32 dmPelsHeight;
        public Int32 dmDisplayFlags;
        public Int32 dmDisplayFrequency;
        public Int32 dmDisplayOrientation;
    }
}