news 2026/9/25 2:57:09

Windows-universal-samples 之 SimpleOrientationSensor 示例:UWP 简易方向传感器的事件与轮询实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Windows-universal-samples 之 SimpleOrientationSensor 示例:UWP 简易方向传感器的事件与轮询实战
  • 示例工程

【免费下载链接】Windows-universal-samples

API samples for the Universal Windows Platform.

项目地址:https://gitcode.com/gh_mirrors/wi/Windows-universal-samples
点击查看免费下载

本指南以 Windows-universal-samples 仓库中的 SimpleOrientationSensor 示例 为核心,系统讲解 UWP 应用如何通过Windows.Devices.Sensors.SimpleOrientationSensor类获取设备简易方向(未旋转、面朝上、逆时针旋转 90 度等)。文中不仅完整还原官方示例的构建与运行步骤,还结合仓库内 C# 与 C++/CX 双语言源码,深入剖析数据事件监听与轮询读取两种场景的完整实现、UI 线程调度与可见性处理细节,帮助读者直接套用并二次开发自己的方向感应功能。

示例概览与核心 API

SimpleOrientationSensor(简易方向传感器)与需要三轴数据的 OrientationSensor 不同,它返回的是离散的六个方向状态,非常适合实现"旋转屏幕提示""设备翻转检测"这类轻量级需求。本示例位于仓库的 Samples/SimpleOrientationSensor 目录,官方描述为:

Shows how to use the Windows.Devices.Sensors.SimpleOrientationSensor class for a simple device orientation sensor.

示例允许用户实时查看设备简易方向值,并提供两种可选场景:

  • Orientation sensor data events(数据事件):注册OrientationChanged事件监听,传感器方向变化时实时推送更新;
  • Polling orientation sensor readings(轮询读取):手动调用GetCurrentOrientation()获取当前方向快照。

核心 API 位于Windows.Devices.Sensors命名空间,关键成员如下:

成员类型说明
SimpleOrientationSensor.GetDefault()静态方法获取系统默认方向传感器实例;设备不支持时返回null
OrientationChanged事件方向变化时触发,事件参数为SimpleOrientationSensorOrientationChangedEventArgs,其Orientation属性携带新方向
GetCurrentOrientation()方法同步读取当前方向(轮询场景使用)

方向枚举SimpleOrientation的取值,可从源码中的DisplayOrientation辅助方法(Scenario1_DataEvents.xaml.cs)完整看到:

  • NotRotated——未旋转;
  • Rotated90DegreesCounterclockwise——逆时针旋转 90 度;
  • Rotated180DegreesCounterclockwise——逆时针旋转 180 度;
  • Rotated270DegreesCounterclockwise——逆时针旋转 270 度;
  • Faceup——面朝上;
  • Facedown——面朝下;
  • 其他情况统一显示为Unknown orientation。

工程结构与双语言实现

示例按语言分为两个独立子工程,均包含相同的两个场景页面:

Samples/SimpleOrientationSensor/ ├── cpp/ # C++/CX(Windows Runtime C++)版本 │ ├── Scenario1_DataEvents.xaml / .cpp / .h │ ├── Scenario2_Polling.xaml / .cpp / .h │ ├── SampleConfiguration.h / .cpp │ ├── SimpleOrientationSensor.sln / .vcxproj │ └── Package.appxmanifest └── cs/ # C# 版本 ├── Scenario1_DataEvents.xaml / .xaml.cs ├── Scenario2_Polling.xaml / .xaml.cs ├── SampleConfiguration.cs ├── SimpleOrientationSensor.sln / .csproj └── Package.appxmanifest

两个语言版本的场景入口由 SampleConfiguration.cs(C++ 侧对应SampleConfiguration.h/.cpp)统一注册:

public const string FEATURE_NAME = "Simple Orientation Sensor"; List<Scenario> scenarios = new List<Scenario> { new Scenario() { Title = "Data Events", ClassType = typeof(SimpleOrientationCS.Scenario1_DataEvents) }, new Scenario() { Title = "Polling", ClassType = typeof(SimpleOrientationCS.Scenario2_Polling) } };

清单文件 Package.appxmanifest 声明了Windows.Universal目标设备家族,MinVersion为10.0.10240.0、MaxVersionTested为10.0.22621.0,即面向 Windows 10 及以上版本的通用应用。

场景一:数据事件(Data Events)

数据事件场景的界面(Scenario1_DataEvents.xaml)包含Enable / Disable两个按钮与一个方向输出TextBlock,其说明文字为:"Registers an event listener for orientation changes and displays the new orientation as it is reported."

获取传感器实例

页面构造函数中调用静态工厂方法获取默认传感器,并处理设备不支持的情况(Scenario1_DataEvents.xaml.cs):

private SimpleOrientationSensor _sensor; public Scenario1_DataEvents() { this.InitializeComponent(); _sensor = SimpleOrientationSensor.GetDefault(); if (_sensor == null) { rootPage.NotifyUser("No simple orientation sensor found", NotifyType.ErrorMessage); } }

这是所有 UWP 传感器用法的标准模式:先判空,再使用。在没有方向传感器的设备(如部分模拟器或台式机)上运行会得到明确错误提示。

注册与注销事件

点击 Enable 后注册事件并立即显示一次当前方向(Scenario1_DataEvents.xaml.cs):

private void ScenarioEnable(object sender, RoutedEventArgs e) { if (_sensor != null) { Window.Current.VisibilityChanged += new WindowVisibilityChangedEventHandler(VisibilityChanged); _sensor.OrientationChanged += new TypedEventHandler<SimpleOrientationSensor, SimpleOrientationSensorOrientationChangedEventArgs>(OrientationChanged); ScenarioEnableButton.IsEnabled = false; ScenarioDisableButton.IsEnabled = true; // Display the current orientation once while waiting for the next orientation change DisplayOrientation(ScenarioOutput_Orientation, _sensor.GetCurrentOrientation()); } else { rootPage.NotifyUser("No simple orientation sensor found", NotifyType.ErrorMessage); } }

两个实现细节值得注意:

  1. 注册事件的同时也调用GetCurrentOrientation():事件只在方向变化时触发,因此先主动读取一次当前值,避免按钮点击后界面一直停留在 "No data";
  2. 同时注册Window.Current.VisibilityChanged:当应用窗口不可见时注销传感器事件,可见时重新注册(见 VisibilityChanged 处理)。源码注释明确指出:不可见时注销事件可避免传感器数据引发非预期操作,恢复可见后无需手动恢复reportInterval,系统在应用恢复时会自动恢复。

Disable 按钮反向操作,同时注销两类事件并切换按钮可用状态(Scenario1_DataEvents.xaml.cs)。

事件回调与 UI 线程调度

OrientationChanged回调运行在后台线程,必须通过Dispatcher编组到 UI 线程后才能更新TextBlock(Scenario1_DataEvents.xaml.cs):

async private void OrientationChanged(object sender, SimpleOrientationSensorOrientationChangedEventArgs e) { await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { DisplayOrientation(ScenarioOutput_Orientation, e.Orientation); }); }

C++/CX 版本实现了完全相同的逻辑(Scenario1_DataEvents.xaml.cpp),同样通过Dispatcher->RunAsync(CoreDispatcherPriority::Normal, ...)将e->Orientation送回 UI 线程,并在头文件 Scenario1_DataEvents.xaml.h 中用EventRegistrationToken(visibilityToken/orientationToken)保存事件句柄以便注销。C++ 版在OnNavigatedFrom中还会判断NavigationMode::Forward && e->Uri == nullptr以避免应用挂起(Phone 场景)时误清理事件。

页面生命周期清理

离开页面时,若传感器事件仍处于启用状态,则注销所有事件(C# 的OnNavigatingFrom,见 Scenario1_DataEvents.xaml.cs):

protected override void OnNavigatingFrom(NavigatingCancelEventArgs e) { if (ScenarioDisableButton.IsEnabled) { Window.Current.VisibilityChanged -= new WindowVisibilityChangedEventHandler(VisibilityChanged); _sensor.OrientationChanged -= new TypedEventHandler<SimpleOrientationSensor, SimpleOrientationSensorOrientationChangedEventArgs>(OrientationChanged); } base.OnNavigatingFrom(e); }

这一模式保证了导航离开后不再有悬挂的传感器回调,避免内存泄漏与无效 UI 更新。

场景二:轮询读取(Polling)

轮询场景的界面(Scenario2_Polling.xaml)只有一个Get按钮,说明文字为:"Performs a single request to retrieve the current device orientation."

其代码极为精简,核心逻辑只有一步(Scenario2_Polling.xaml.cs):

private void ScenarioGet(object sender, RoutedEventArgs e) { if (_sensor != null) { DisplayOrientation(ScenarioOutput_Orientation, _sensor.GetCurrentOrientation()); } else { rootPage.NotifyUser("No simple orientation sensor found", NotifyType.ErrorMessage); } }

GetCurrentOrientation()是同步方法,返回SimpleOrientation枚举值,不涉及事件注册与线程编组——适合需要"按需读取、低功耗"的场景。C++/CX 版实现完全一致(Scenario2_Polling.xaml.cpp)。

两种场景如何选择

维度数据事件(Data Events)轮询(Polling)
数据获取方式事件驱动,方向变化自动推送手动调用GetCurrentOrientation()
适用场景实时响应方向变化(如自动旋转 UI、翻转检测)按需读取一次快照(如进入页面时读取初始方向)
线程要求回调在后台线程,需Dispatcher编组到 UI 线程同步调用,无线程切换负担
资源开销持续监听,需在不可见/离开页面时注销无持续监听,按需消耗

构建与运行

系统要求

  • Windows 10 及以上操作系统;
  • Visual Studio(含 UWP 开发工作负载,支持 C# 与 C++/CX)。

构建步骤

  1. 若通过 ZIP 方式获取示例,务必解压整个压缩包,而不是只解压单个示例文件夹——整个 Windows-universal-samples 集合共享SharedContent依赖(本示例的 frontmatter 中extendedZipContent即声明了SharedContent与LICENSE的关联);
  2. 启动 Visual Studio,选择File>Open>Project/Solution;
  3. 在解压目录下进入Samples/SimpleOrientationSensor子文件夹,再进入首选语言的子目录(cs或cpp),双击其中的解决方案文件(.sln);
  4. 按Ctrl+Shift+B,或选择Build>Build Solution完成构建。

运行与部署

  • 仅部署:选择Build>Deploy Solution;
  • 部署并调试运行:按F5,或选择Debug>Start Debugging;
  • 部署并无调试运行:按Ctrl+F5,或选择Debug>Start Without Debugging。

运行后进入 "Simple Orientation Sensor" 示例页:选择Data Events场景点击 Enable,旋转或翻转设备即可看到方向实时刷新;选择Polling场景点击 Get,则单次读取当前方向。若设备无方向传感器,界面会显示 "No simple orientation sensor found" 错误提示。

参考与延伸

  • 本示例曾提供 JavaScript(HTML/JS)版本,现已归档至 archived/SimpleOrientationSensor 目录;
  • 仓库中还包含传感器家族的其他示例,如 OrientationSensor(三轴姿态传感器)、Accelerometer(加速度计)、Inclinometer(倾角计),接口模式与本示例一致(GetDefault()+ 事件/轮询双场景),可相互参照;
  • 公共 UI 模板与共享代码位于 SharedContent/Templates 与 SharedContent/cpp(C++ 版示例依赖其中的共享 XAML 与基础设施)。
  • 示例工程

【免费下载链接】Windows-universal-samples

API samples for the Universal Windows Platform.

项目地址:https://gitcode.com/gh_mirrors/wi/Windows-universal-samples
点击查看免费下载
上一篇:企业级Azure文档自动化:AzViz与CI/CD流程集成实践
下一篇:Ambrose平台详解:数据工作流可视化与实时监控的终极解决方案

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/25 2:55:13

CTF逆向Hidden Key实战:AI辅助破解控制流平坦化与信号处理

上周末打了一场线上CTF&#xff0c;有一道100分的逆向题叫Hidden Key&#xff0c;我一开始真没当回事。名字看着像是让你去字符串里翻一个藏起来的key&#xff0c;结果附件是个strip过的64位ELF&#xff0c;运行之后只有一句Usage: ./hidden_key <key>&#xff0c;输错就…

作者头像 李华
网站建设 2026/9/25 2:55:06

Nmap内网隐蔽扫描实战:从原理到参数组合全面解析

Nmap大概是每个做网络的人电脑里都装过的工具&#xff0c;但大部分人对它的认识停留在nmap 192.168.1.1这种简单命令上。能扫出端口、扫出服务&#xff0c;就算“会用”了。可真到了内网场景&#xff0c;尤其是要做一次完整资产盘点、又不希望把安全设备告警刷屏的时候&#xf…

作者头像 李华
网站建设 2026/9/25 2:54:37

ESP32上跑WebAssembly:从固件原理到运行时实践的完整解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华