如何在UWP/WinUI中检测系统时间变更事件?
UWP/WinUI 系统时间变更监听实现方案
不需要轮询,组合系统原生推送事件就能覆盖全部需求场景:手动修改系统日期时间、NTP自动校时完成、时区变更、自动时区/自动时间开关触发的时间调整,性能和Android、iOS端的系统广播监听方案完全一致。
具体实现
- 时间调整事件监听(覆盖手动改时间、NTP校时完成场景)
Windows系统在时间发生调整时,会向所有顶层窗口推送WM_TIMECHANGE消息(消息值0x001E),旧版.NET Framework里的Microsoft.Win32.SystemEvents.TimeChanged本质就是对这个消息的托管封装。- WinUI 3(Windows App SDK)项目:直接子类化主窗口过程拦截该消息即可,参考代码:
代码里用到的private const int WM_TIMECHANGE = 0x001E; private const int GWLP_WNDPROC = -4; private IntPtr _originalWndProc; private delegate IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam); protected override void OnWindowCreated(WindowCreatedEventArgs args) { base.OnWindowCreated(args); var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(this); WndProc proc = (hWnd, m, w, l) => { if (m == WM_TIMECHANGE) { // 触发NTP时间重校验逻辑 _ = ReValidateSystemTimeViaNTP(); } return CallWindowProc(_originalWndProc, hWnd, m, w, l); }; _originalWndProc = SetWindowLongPtr(hwnd, GWLP_WNDPROC, Marshal.GetFunctionPointerForDelegate(proc)); }SetWindowLongPtr、CallWindowProc是User32.dll提供的原生函数,手动写P/Invoke声明或者用代码生成工具自动生成签名即可,不需要额外依赖。 - UWP项目:不需要写Win32互操作代码,直接注册系统自带的
SystemTriggerType.TimeChange后台任务触发器就行,这个触发器由系统在时间变更时主动推送,不需要应用前台常驻,适配成本更低。
- WinUI 3(Windows App SDK)项目:直接子类化主窗口过程拦截该消息即可,参考代码:
- 时区变更事件监听
直接使用Windows.System.TimeZoneSettings.TimeZoneChanged事件就可以,用户手动修改时区、系统根据定位自动切换时区时都会触发这个事件,全版本兼容。
方案说明
- 所有事件都是系统主动推送,没有轮询方案的空转资源损耗,触发延迟在毫秒级
- 覆盖所有需求场景,不会漏判手动改时间、自动校时、时区切换三类操作
- 应用在后台时收到的变更通知,会在应用回到前台时立即投递,不会错过重校验时机
- Xamarin.Forms适配很简单:在UWP/WinUI端的依赖服务里实现上述监听逻辑,通过
MessagingCenter向共享层发通知即可,和Android、iOS端的触发逻辑保持一致。
UWP项目需要引用对应版本的Windows桌面扩展SDK才能使用窗口消息拦截能力,这个能力在Windows 10 10240及以上版本都支持,没有版本兼容问题。
内容的提问来源于stack exchange,提问作者BurkusCat
相关产品推荐
相关产品推荐

