在二合一平板上面,屏幕旋转之后,屏幕的宽高会被改变,如果代码里面有用到屏幕宽高的地方可能会出错。
获取屏幕宽高位置可以通过可以通过如下几种方式获取
/// <summary>/// 获取屏幕大小 /// </summary>public void InitScreenSize(){var primaryScreen = Screen.PrimaryScreen;// 获取主屏幕边界var screenBounds = primaryScreen.Bounds;var screenWidth = screenBounds.Width;var screenHeight = screenBounds.Height;var screenWidth = SystemParameters.PrimaryScreenWidth;var screenHeight = SystemParameters.PrimaryScreenHeight;var Width = SystemParameters.WorkArea.Width;var Height = SystemParameters.WorkArea.Height;}
现在问题是,如果一开始初始化界面就获取屏幕宽高,正常是1920x1080的,屏幕旋转到竖屏之后就会变成1080x1920了。
如何动态适配呢。可以通过如下SimpleOrientationSensor 方式监听屏幕的旋转变化。
internal class OrientationManager{#region 监听方向变化private SimpleOrientationSensor simpleSensor;private SimpleOrientation currentOrientation;/// <summary>/// 监听方向变化重启应用/// </summary>public void RegisterOrientationChanged(){try{if (simpleSensor != null){simpleSensor.OrientationChanged -= SimpleSensor_OrientationChanged;}simpleSensor = SimpleOrientationSensor.GetDefault();AnnotatorService.Log.Info($"初始化方向传感器:{simpleSensor != null}");if (simpleSensor != null){currentOrientation = simpleSensor.GetCurrentOrientation();// 订阅方向变化事件simpleSensor.OrientationChanged += SimpleSensor_OrientationChanged;CheckSensorStatus();}}catch (Exception e){AnnotatorService.Log.Error(e);}}public void UnregisterOrientationChanged(){if (simpleSensor != null){simpleSensor.OrientationChanged -= SimpleSensor_OrientationChanged;simpleSensor = null;}}public Action<SimpleOrientation> OnDelayOrientationChanged;private void CheckSensorStatus(){try{// 定期检查传感器状态var timer = new System.Threading.Timer(_ =>{if (simpleSensor != null){var current = simpleSensor.GetCurrentOrientation();var hasChanged = currentOrientation == current;AnnotatorService.Log.Debug($"定时获取传感器当前方向: {current},是否变化:{hasChanged}");}}, null, TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(30));}catch (Exception ex){AnnotatorService.Log.Error($"传感器状态检查失败: {ex.Message}");}}private async void SimpleSensor_OrientationChanged(SimpleOrientationSensor sender, SimpleOrientationSensorOrientationChangedEventArgs args){AnnotatorService.Log.Info($"方向变化:{args.Orientation}");if (currentOrientation == args.Orientation) return;currentOrientation = args.Orientation;if (IsSignificantOrientationChange(currentOrientation)){await Task.Delay(300);OnDelayOrientationChanged?.Invoke(args.Orientation);}return;if (MainWindowManger.MainWindow != null) return;var exePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H3CAnnotator.exe");if (File.Exists(exePath)){AnnotatorService.Log.Info($"关闭应用重启");Process.Start(exePath);//方向变化重启}}private bool IsSignificantOrientationChange(SimpleOrientation newOrientation){// 过滤掉不重要的方向变化// 例如:Faceup/Facedown 可能不需要处理switch (newOrientation){case SimpleOrientation.Faceup:case SimpleOrientation.Facedown:return false;default:return true;}}#endregion}
SimpleOrientationSensor 监听之后发现2个问题:
1.在触发方向变化立即获取屏幕宽高错误获取到的还是旋转前的宽高。由于触发旋转变化之后需要等待一会屏幕旋转好了之后再获取才正确。
2.旋转好了之后等待200ms再获取屏幕宽高是正常的,但是这个OrientationChanged 事件存在失效的情况,目前还不清楚为什么有时候用一会就事件没触发了,还未定位到原因。
未来解决在代码里面获取屏幕宽高的获取错误的情况,做了如下处理。
在获取宽高的地方直接调用获取宽高,不要进行首次初始化这类的缓存操作。
建议检测代码里面获取屏幕宽高或者是任务栏宽高,工作区域宽高的位置是否有进行缓存处理,需要都改为实时获取。
获取主屏幕分辨率的过程耗时极短,通常在微秒级别。没有必要缓存,即使上万次获取也是极端。