在Windows Mobile (WM) 设备上,事件通知是一种常见的机制,用于告知用户或应用程序某些特定事件发生了。这些事件可以是系统事件、时间事件或者基于时间周期的事件。本文将介绍如何查看和管理这些通知事件,以及如何通过编程方式订阅这些事件。
要查看WM设备上的所有已知通知,可以使用特定的工具。这些工具可以浏览事件数据库,并检查已定义的事件。此外,它们还可以显示电源变化通知。
例如,中间窗口可能显示了一个定时事件,该事件将在午夜0:00发生,并启动 \windows\calupd.exe
。这将使设备整夜保持唤醒状态,并更新日历条目等的重复日程。
右侧窗口显示了挂起/恢复周期中的电源通知。
使用选项菜单,可以保存已定义的通知事件列表。通知事件有多种类型:
public enum CeNotificationType
{
CNT_EVENT = 1, // 系统事件通知
CNT_TIME, // 基于时间的通知
CNT_PERIOD, // 激活时间段内的通知
CNT_CLASSICTIME // 等同于使用CeSetUserNotification函数(已弃用)
}
请注意,并非所有设备都支持所有这些类型。由于名称已经相当直观,这里不再进一步解释这些事件类型。
如果想添加自己的周期性、定时或应用程序通知,可以查看Tasker应用程序。
虽然与上述事件数据库没有直接关系,但了解如何订阅电源通知也很有用。示例使用MS PowerNotifications消息队列。注册电源消息时,可以定义一个过滤器,以便只获取感兴趣的电源通知消息。
const uint POWER_NOTIFY_ALL = 0xFFFFFFFF;
const uint PBT_TRANSITION = 0x00000001; // 系统电源状态转换
const uint PBT_RESUME = 0x00000002; // 通知恢复,指定先前状态
const uint PBT_POWERSTATUSCHANGE = 0x00000004; // 电源供应切换到/从AC/DC
const uint PBT_POWERINFOCHANGE = 0x00000008; // 每条消息都带有数据结构
有很多标志需要查找:
[Flags]
enum PowerState : uint
{
POWER_STATE_NA = 0x00,
POWER_STATE_ON = 0x00010000,
POWER_STATE_OFF = 0x00020000,
POWER_STATE_CRITICAL = 0x00040000,
POWER_STATE_BOOT = 0x00080000,
POWER_STATE_IDLE = 0x00100000,
POWER_STATE_SUSPEND = 0x00200000,
POWER_STATE_RESET = 0x00800000,
}
当然,还需要一些P/Invoke:
#region DllImports
[DllImport("coredll.dll")]
private static extern IntPtr RequestPowerNotifications(IntPtr hMsgQ, uint Flags);
[DllImport("coredll.dll")]
private static extern uint WaitForSingleObject(IntPtr hHandle, int wait);
[DllImport("coredll.dll")]
private static extern IntPtr CreateMsgQueue(string name, ref MsgQOptions options);
[DllImport("coredll.dll")]
private static extern bool ReadMsgQueue(IntPtr hMsgQ, byte[] lpBuffer, uint cbBufSize, ref uint lpNumRead, int dwTimeout, ref uint pdwFlags);
#endregion
主要工作是在线程函数中完成的:
private void DoWork()
{
byte[] buf = new byte[10000];
uint nRead = 0, flags = 0, res = 0;
System.Diagnostics.Debug.WriteLine("starting loop");
try
{
while (!done)
{
res = WaitForSingleObject(ptr, 2500);
if (res == 0)
{
ReadMsgQueue(ptr, buf, (uint)buf.Length, ref nRead, -1, ref flags);
System.Diagnostics.Debug.WriteLine("message: " + ConvertByteArray(buf, 0) + " flag: " + ConvertByteArray(buf, 4));
uint flag = ConvertByteArray(buf, 4);
string msg = "";
msg += ((PowerState)flag).ToString();
if (msg == "")
msg = "Unknown Flag: " + flag.ToString();
if (msg == "0")
msg = "POWER_STATE_NA";
if (msg != "")
{
if (OnMsg != null)
OnMsg(this, new PwrEventArgs(msg, flag));
System.Diagnostics.Debug.WriteLine(msg);
}
}
}
}
catch (Exception ex)
{
if (!done)
{
System.Diagnostics.Debug.WriteLine("Got exception: " + ex);
}
}
System.Diagnostics.Debug.WriteLine("loop ended");
}