分为两种情况:
一、自己用SHNotificationAdd 创建出来的Notification,当然是用SHNotificationRemove来去掉了。
二、系统的Notification(比方说未接电话、新短信之类的),可以用以下的方法:
通过修改注册表[HKEY_CURRENT_USER/System/State]下一些相关的键值。
e.g.
要去掉未接电话Notificatio,修改如下:
[HKEY_CURRENT_USER/System/State/Phone]
"Missed Call Count"=0
去掉新短消息Notification,修改如下:
[HKEY_CURRENT_USER/System/State/Messages/sms/Unread]
"Count"=0
上次说修改键值来达到删除Notification的目的,但可能会产生副作用,比方说Today Screen里面的计数可能会因为这个注册表的改动而显示了错误的值。
[HKEY_CURRENT_USER/System/State/Messages/sms/Unread]
"Count"=0
后来在网上搜了一下,codeproject上有个人是通过SHNotificationRemove实现的,我修改了一下,sample code如下:
- void RemoveNewMessageNotification()
- {
- SHNOTIFICATIONDATA shnd;
- CLSID clsid;
- LRESULT result;
- DWORD dwID = 0;
- if (0 == CLSIDFromString(TEXT("{A877D65B-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 < 20000));
- }
- }
系统菜单扩展
系统菜单的扩展是通过COM来实现的,主要工作有两个:代码实现和创建注册表键值。
1. 代码实现:
实现接口为IObjectWithSite和IContextMenu。当然,还包括IClassFactory,它帮助生成指定CLSID的对象,它的代码其实都是千篇一律,把sample中的代码稍微修改一下就可以用了。
具体的实现请参考<SDK安装路径>/Samples/Common/CPP/Win32/InboxMenuExtensibility下的一个例子,它扩展了tmail.exe(Messaging) message list下的menu。
关键的实现主要还是在QueryContextMenu和InvokeCommand,QueryContextMenu一般用来添加菜单的操作,InvokeCommand是用于点击你刚添加的菜单项时的响应。值得一提的是QueryContextMenu的返回值,应设为你添加的菜单项个数,一般实现为return MAKE_HRESULT(SEVERITY_SUCCESS, 0, nMenuAdded); 这样系统就知道你到底添加了多少菜单,别人调用QueryContextMenu的时候idCmdFirst才是正确的。比方说其它应用程序恰好也在这个菜单里加了菜单项,就不会引起冲突(冲突就是说比方说点了你的菜单项,结果响应的却是其它软件加的菜单项的命令)。而且Smart Phone也比较特殊,每进到一个popup menu就会响应一下QueryContextMenu,所以一般都是计算当前弹出菜单的菜单项个数来避免每次进去一个popup menu都添加菜单项。
2. 注册表键值的创建:
[HKEY_CLASSES_ROOT/CLSID]下创建一个key,name为你所用的CLSID,再在这个key下面创建一个key,name为InProcServer32,默认值设为你的DLL。
[HKEY_LOCAL_MACHINE/Software/Microsoft/Shell/Extensions/ContextMenus]下创建的key需要根据你扩展菜单的位置来决定的,具体的值请看SDK document中的Menu Overview。
State and Notifications Broker
State and Notifications Broker提供了一个在注册表中存储系统和应用程序信息的机制和一个存储信息改变的通知系统。它可以用于监控系统中的任何注册表键值。通知种类包括以下几种: - System state information, such as features present (camera, keyboard), active application, cradled state, battery state.
- Message information, such as count of unread, last received, account info.
- Tasks and appointments information, such as upcoming, overdue, location.
- Windows Media Player information, such as currently playing album, artist.
- Phone information, such as signal information, operator information, call information, multiline information.
- Connections information, related to bluetooth, cellular, network, modem, etc.
snapi.h中包含了需要监控的注册表Key、Path、Value Name和Mask,比方说你想知道现在的phone处在一个什么状态,可以看到snapi.h中有这么一段:
////////////////////////////////////////////////////////////////////////////////
// PhoneRoaming
// Gets a value indicating whether the phone is currently in roaming mode.
#define SN_PHONEROAMING_ROOT HKEY_LOCAL_MACHINE
#define SN_PHONEROAMING_PATH TEXT("System//State//Phone")
#define SN_PHONEROAMING_VALUE TEXT("Status")
#define SN_PHONEROAMING_BITMASK 0x200当键值[HKLM/System/State/Phone] "Status"值的0x200这一位上为1时,说明phone处在漫游状态。
那么,如何监控注册表键值呢?可以用RegistryNotifyApp、RegistryNotifyWindow、RegistryNotifyCallback等API。以下是Sample Code:
- #include <snapi.h>
- #include <regext.h>
- #define UM_REGNOTIFY WM_USER+1000
- // Global Variables:
- HREGNOTIFY g_hRegNotify;
- LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
- {
- switch (message)
- {
- case WM_CREATE:
- NOTIFICATIONCONDITION nc;
- ZeroMemory(&nc, sizeof(NOTIFICATIONCONDITION));
- nc.ctComparisonType = REG_CT_EQUAL;
- nc.dwMask = 0x200;
- nc.TargetValue.dw = 0x200;
- RegistryNotifyWindow(SN_PHONEROAMING_ROOT, SN_PHONEROAMING_PATH, SN_PHONEROAMING_VALUE, hWnd, UM_REGNOTIFY, 0, &nc, &g_hRegNotify);
- break;
- case UM_REGNOTIFY:
- MessageBox(hWnd, _T("Phone is roaming!"), _T("Notification Broker"), MB_OK);
- break;
- case WM_DESTROY:
- RegistryCloseNotification(g_hRegNotify);
- PostQuitMessage(0);
- break;
- default:
- return DefWindowProc(hWnd, message, wParam, lParam);
- }
- return 0;
- }