65.9K
CodeProject 正在变化。 阅读更多。
Home

Windows Mobile – 移除“备用电池电量非常低”通知气球

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.57/5 (4投票s)

2005年8月30日

CPOL

3分钟阅读

viewsIcon

65509

如何以编程方式删除恼人的“备用电池电量严重不足”(虚假)关键通知。

引言

以下代码片段演示了一种以编程方式从系统中删除“备用电池电量严重不足”系统通知消息气泡以及从 Windows Mobile 设备屏幕导航栏中删除其图标的方法。为什么这很有用以及它解决了什么问题将在下一节“背景”中进行讨论。

背景

每当设备的备用电池电量严重不足时,基于 Windows Mobile 的 Pocket PC 设备就会弹出一个关键系统通知气泡,并在导航栏中显示一个图标,以通知用户系统备用电池电量已严重不足。这确实是设备的一个关键状况,用户需要迅速采取行动更换/充电备用电池,以避免潜在的数据丢失。

然而,当前市场上的某些设备要么无法接触到备用电池的位置以便更换,要么即使更换了电池,在设备重启电源时,消息气泡仍会时不时地弹出。在后一种情况下,这是一种虚假情况,令许多人感到恼火。

虽然此通知会在用户确认弹出通知后消失,但对于作为 Kiosk(全屏模式)运行的应用程序来说,情况完全不同。在这种情况下,通知消息气泡永远不会弹出,但图标会显示在导航栏中,并且无法将其移除。

我为上述情况找到了一个简单的解决方法。您可以根据需要使用此解决方法。

使用代码

该解决方法背后的逻辑非常简单。尽管如此,其中包含了一些技巧。逻辑是枚举系统通知,找到“备用电池电量严重不足”通知的句柄,如果找到,则以编程方式从系统中删除该通知。

首先,请谨慎设置一种机制来区分此通知弹出时的虚假情况和用户 **应** 采取适当行动以防止潜在数据丢失的实际情况。

其次,您可能需要一种方法从其文本形式获取通知 COM 接口的 CLSID。您可以如代码片段所示使用 CLSIDFromString() 函数。此函数已在 ole32.liboleaut32.lib 库中实现。您可能还想在项目中 #include objbase.h 头文件。

此外,SHNotificationGetData() 函数调用需要传递一个唯一的通知 ID,而我们没有这个 ID。不同的平台供应商已为此相同通知分配了不同的 ID,使得猜测变得更加困难。因此,在我的解决方法中,我尝试从 0 开始递增 ID,每次调用失败时按顺序递增 1。在我尝试过的所有平台上,都可以在不到 2000 次尝试内找到匹配的 ID。您可能想先在您开发的平台上进行实验,以便获得一些想法。如果您的平台供应商能提供此 ID 值,那就太好了。如果不能,您仍然可以使用我使用的方法。

我已成功在具有 Windows Mobile 2002/2003/2003SE 设备的 eVC++ 3.0 和 4.0 项目中使用了此方法。

//*********************************************************************************
//* Method Name: RemoveLowBattMessage()
//*
//* Description: Remove the "Backup Battery Very Low" Notification.
//*
//* Argument(s): none
//* Return type: void
//********************************************************************************
void RemoveLowBattMessage()
{
     SHNOTIFICATIONDATA shnd;
     CLSID clsid;
     LRESULT result;
     DWORD dwID = 0;
 
     if (0 == CLSIDFromString(TEXT("{A877D663-239C-47a7-9304-0D347F580408}"), 
                                                                   &clsid)) {
         memset(&shnd, 0, sizeof(shnd));
         shnd.cbStruct = sizeof(SHNOTIFICATIONDATA);
         do {
              result = SHNotificationGetData(&clsid,dwID,&shnd);
              if (ERROR_SUCCESS == result) {
                   SHNotificationRemove(&clsid,dwID);
                   if (shnd.pszHTML) free((void *) shnd.pszHTML);
                   shnd.pszHTML = NULL;
                   if (shnd.pszTitle) free((void *) shnd.pszTitle);
                   shnd.pszTitle = NULL;
              } else dwID++;
         } while ((ERROR_SUCCESS != result) && (dwID < 2000));
     };
}

关注点

我花了很多时间思考这个问题,这很有趣。这个虚假的警告信息困扰了我们很长时间,直到我想到这个以编程方式移除它的方法。这个逻辑并没有什么神奇之处。而且,同样的方法也可以用来移除您可能不想要的任何系统通知。不过,请务必小心!

历史

  • 2005 年 8 月 30 日 – 首次发布到 The Code Project。
© . All rights reserved.