您的位置:首页 > 其它

CE MAPI实例讲解 --- IMAPIAdviseSink的一个例子(四)

2008-10-24 19:25 363 查看
AdviseSink对于我们了解系统SMS以及OUTLOOK的消息运作有很大帮助,我们可以挂接到SMS、OUTLOOK的Message Store上,看看在做某些操作时,系统到底对Message做了些什么。下面我举个一个例子来说明它的用途:
不知道大家有没有注意,在Smartphone上的Deleted Box里面有个按钮叫Restore,即恢复功能,如果是你用系统菜单把一条Message删除到Deleted Box的话,Restore可以正常工作,但是如果你用MAPI去操作呢?比如IMAPIFolder::CopyMessages,你可以试一下,这个时候Restore失效了,由此可见系统在用菜单删除Message的时候自己做了些手脚,那我们怎么知道它具体做了哪些事情呢?这个时候IMAPIAdviseSink就派上用场了,不过在这之前先简要介绍一下MAPI属性,我们可以看一下mapitags.h中关于属性的定义,非常明显,一个属性由类型和ID两个部分通过PROP_TAG宏作用生成。类型代表这个属性的值是以什么形式存放在数据库里面的,这关系到你能否正确读写该属性,比如我们在调用IMessage:: GetProps时候,返回了结构体SPropValue:
typedef union _PV
{
short int i; /* case PT_I2 */
LONG l; /* case PT_LONG */
ULONG ul; /* alias for PT_LONG */
float flt; /* case PT_R4 */
double dbl; /* case PT_DOUBLE */
unsigned short int b; /* case PT_BOOLEAN */
CURRENCY cur; /* case PT_CURRENCY */
double at; /* case PT_APPTIME */
FILETIME ft; /* case PT_SYSTIME */
LPSTR lpszA; /* case PT_STRING8 */
SBinary bin; /* case PT_BINARY */
LPWSTR lpszW; /* case PT_UNICODE */
LPGUID lpguid; /* case PT_CLSID */
…….
} __UPV;

typedef struct _SPropValue
{
ULONG ulPropTag;
ULONG dwAlignPad;
union _PV Value;
} SPropValue, FAR * LPSPropValue;
看到union _PV了吗,我们如何知道该取哪个值来用呢?这就得通过属性的类型来告诉我们了,我们可以通过宏PROP_TYPE来获取一个属性的类型,通过PROP_ID来获取ID。

好了,下面是OnNotify实现:
ULONG CAdviseSink::OnNotify(ULONG cNotif, LPNOTIFICATION lpNotifications)
{
if(cNotif > 0 && NULL != lpNotifications)
{
for(int i = 0; i < (int)cNotif; ++i)
{
switch(lpNotifications[i].ulEventType)
{
//Message 发生了改变,这时lpNotifications[i].info.obj.lpPropTagArray就代表了发生改变的属性值列表。
case fnevObjectModified:
{
// iPropCount : 表示一共有多少个属性发生了改变
int iPropCount = lpNotifications[i].info.obj.lpPropTagArray->cValues;
for(int j = 0; j < iPropCount; j++)
{
// ulPropType : 属性类型,即PT_LONG,PT_DOUBLE,PT_BINARY等等,定义可以在mapidefs.h里面找到
// ulPropID : 属性ID,可以在mapitags.h里面找到
// 在此处打上断点或者打上日志,我们就可以知道在系统删除Message时,对它到底做了什么。
ULONG ulPropType = PROP_TYPE(lpNotifications[i].info.obj.lpPropTagArray->aulPropTag[j]);
ULONG ulPropID = PROP_ID(lpNotifications[i].info.obj.lpPropTagArray->aulPropTag[j]); }
break;
}
default:
break;
}
}
}
return 0;
}

按照上一篇介绍的方法,把它挂到SMS Store上,启动调试状态,等待Modified事件发生。然后到系统收件箱中创建一条新的SMS,并且删除它,前面新建时的通知我们不关心,当删除时OnNotify一共会收到3次通知消息,认真观察,第一次类型为3(PT_LONG),ID为13827(PR_CONTENT_UNREAD),第二次也一样,第三次呢,类型为258(PT_BINARY),ID为34072,恩?这并不是标准的属性,从SDK上看从0x8000到0xFFFE应该是用户自定义属性区域,可见这是MS在实现SMS程序时自己添加的一个属性,做什么用呢?类型是PT_BINARY,会不会是这条Message原始所在Box的EntryID呢?把它的数据打印出来和Draft Box的EntryID一比较,果然一模一样,这下明白了,MS在这里做了个手脚,在它自己的程序里面删除MESSAGE时,会添加一个自定义的属性,并把MESSAGE原始所在BOX的EntryID写进去,等到点Restore时,就读取这个值,把MESSAGE恢复回去,我们利用MAPI操作的MESSAGE没有置这个属性,当然不起作用了,所以我们所要做的只是在CopyMessage之前,把这个属性写上而已,这时再试一把,OK,搞定。
这只是一个简单的例子,AdviseSink对于平时对MAPI的调试很有帮助,从注册时的那一堆标志就可以看出,它不仅仅是用来监视Message而已,功能还是很强大的,不过我个人对其他功能倒没有很深入的研究,就不做介绍了,如果有朋友做过类似方面的研究,请告知我下,也让我学习一下。
OK,今天先写到这里,下篇将继续讨论IMAPIAdviseSink,主要是讲如何在OnNotify中取得被改变的Message对象。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: