一定是无边框App才可以做到;
首先是获取屏幕当前显示方向工具类:
public class NativeMethods
{
public const int ENUM_CURRENT_SETTINGS = -1;
public enum DisplayOrientation { Default = 0, Landscape = 0, Portrait, Landscape_Flipped, Portrait_Flipped }
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct DEVMODE
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string dmDeviceName;
public short dmSpecVersion;
public short dmDriverVersion;
public short dmSize;
public short dmDriverExtra;
public int dmFields;
public int dmPositionX;
public int dmPositionY;
public int dmDisplayOrientation;
public int dmDisplayFixedOutput;
public short dmColor;
public short dmDuplex;
public short dmYResolution;
public short dmTTOption;
public short dmCollate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string dmFormName;
public short dmLogPixels;
public short dmBitsPerPel;
public int dmPelsWidth;
public int dmPelsHeight;
public int dmDisplayFlags;
public int dmDisplayFrequency;
public int dmICMMethod;
public int dmICMIntent;
public int dmMediaType;
public int dmDitherType;
public int dmReserved1;
public int dmReserved2;
public int dmPanningWidth;
public int dmPanningHeight;
};
public static DisplayOrientation getDisaplayState()
{
// initialize the DEVMODE structure
DEVMODE dm = new DEVMODE();
dm.dmDeviceName = new String(new char[32]);
dm.dmFormName = new String(new char[32]);
dm.dmSize = (short)Marshal.SizeOf(dm);
if (0 != NativeMethods.EnumDisplaySettings(null, NativeMethods.ENUM_CURRENT_SETTINGS, ref dm))
{
// swap width and height
int temp = dm.dmPelsHeight;
dm.dmPelsHeight = dm.dmPelsWidth;
dm.dmPelsWidth = temp;
switch (dm.dmDisplayOrientation)
{
case 0: return DisplayOrientation.Landscape;
case 1: return DisplayOrientation.Portrait;
case 2: return DisplayOrientation.Landscape_Flipped;
case 3: return DisplayOrientation.Portrait_Flipped;
default: return DisplayOrientation.Default;
}
}
return DisplayOrientation.Default;
}
[DllImport("user32.dll", CharSet = CharSet.Ansi)]
public static extern int EnumDisplaySettings(string lpszDeviceName, int iModeNum, ref DEVMODE lpDevMode);
[DllImport("user32.dll")]
public static extern int ChangeDisplaySettings(ref DEVMODE lpDevMode, int dwFlags);
[DllImport("user32.dll", EntryPoint = "#2507")]//此函数没有函数名,只能通过入口序号调用
public extern static bool SetAutoRotation(bool bEnable);//设置自动旋转状态
}
App启动时,判断一次当前屏幕方向,并进行更改
switch (NativeMethods.getDisaplayState())
{
case NativeMethods.DisplayOrientation.Landscape: _mainViewModel.Angle = 0; break;
case NativeMethods.DisplayOrientation.Portrait: _mainViewModel.Angle = 90; break;
case NativeMethods.DisplayOrientation.Landscape_Flipped: _mainViewModel.Angle = 180; break;
case NativeMethods.DisplayOrientation.Portrait_Flipped: _mainViewModel.Angle = 270; break;
}
主容器添加LayoutTransform布局,并使用MVVM绑定到相关成员变量
<ContentControl.LayoutTransform>
<RotateTransform Angle="{Binding Angle}"></RotateTransform>
</ContentControl.LayoutTransform>
添加更改显示设置时事件
Microsoft.Win32.SystemEvents.DisplaySettingsChanging += (o, e) =>
{
switch (NativeMethods.getDisaplayState())
{
case NativeMethods.DisplayOrientation.Landscape: _mainViewModel.Angle = 0; break;
case NativeMethods.DisplayOrientation.Portrait: _mainViewModel.Angle = 90; break;
case NativeMethods.DisplayOrientation.Landscape_Flipped: _mainViewModel.Angle = 180; break;
case NativeMethods.DisplayOrientation.Portrait_Flipped: _mainViewModel.Angle = 270; break;
}
};