无聊客的专栏

寻找逝去的岁月

原创 (原创)CE MAPI实例讲解 --- IMAPIAdviseSink的一个例子(四)收藏

新一篇: VS2005自动编译设置 | 旧一篇: (原创)CE MAPI实例讲解 --- 监视Message的状态改变(三)

    AdviseSink对于我们了解系统SMS以及OUTLOOK的消息运作有很大帮助,我们可以挂接到SMSOUTLOOKMessage 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_LONGPT_DOUBLEPT_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)ID13827(PR_CONTENT_UNREAD),第二次也一样,第三次呢,类型为258(PT_BINARY),ID34072,恩?这并不是标准的属性,从SDK上看从0x80000xFFFE应该是用户自定义属性区域,可见这是MS在实现SMS程序时自己添加的一个属性,做什么用呢?类型是PT_BINARY,会不会是这条Message原始所在BoxEntryID呢?把它的数据打印出来和Draft BoxEntryID一比较,果然一模一样,这下明白了,MS在这里做了个手脚,在它自己的程序里面删除MESSAGE时,会添加一个自定义的属性,并把MESSAGE原始所在BOXEntryID写进去,等到点Restore时,就读取这个值,把MESSAGE恢复回去,我们利用MAPI操作的MESSAGE没有置这个属性,当然不起作用了,所以我们所要做的只是在CopyMessage之前,把这个属性写上而已,这时再试一把,OK,搞定。

     这只是一个简单的例子,AdviseSink对于平时对MAPI的调试很有帮助,从注册时的那一堆标志就可以看出,它不仅仅是用来监视Message而已,功能还是很强大的,不过我个人对其他功能倒没有很深入的研究,就不做介绍了,如果有朋友做过类似方面的研究,请告知我下,也让我学习一下。

OK,今天先写到这里,下篇将继续讨论IMAPIAdviseSink,主要是讲如何在OnNotify中取得被改变的Message对象。

无聊客

yzx0023@gmail.com

2006.4.26

发表于 @ 2006年04月26日 21:27:00|评论(loading...)|编辑

新一篇: VS2005自动编译设置 | 旧一篇: (原创)CE MAPI实例讲解 --- 监视Message的状态改变(三)

评论

#浪客剑心 发表于2006-08-07 18:13:00  IP: 58.60.131.*
能发一个完整的例子给我吗?谢谢!
#great_mountain 发表于2006-08-10 14:27:00  IP: 10.193.74.*
请问在Moblie 5.0上能监视message状态的改变吗?我在5.0的模拟器上是可以的,但是到了开发板上,死活捕获不了消息.无论是短消息创建还是删除的消息(这些操作是由微软的短信客户端发出的).请问无聊客 这是什么回事啊?先谢谢啦
#yzx0023 发表于2006-08-10 15:59:00  IP: 218.108.41.*
To great_mountain:可以的,在5.0上面请确保你的程序已经签名,并且正确运行
#actionman 发表于2006-09-11 15:48:00  IP: 61.151.255.*
用IMAPIAdviseSink如何实现邮件的发送, 难道只要把邮件放到或移到outbox就好了吗, 如何与真正的发送代码向连接呢
#yzx0023 发表于2006-09-11 21:26:00  IP: 60.176.250.*
To actionman:是的,一般系统默认的邮件或者SMS客户端都会监视移动行为,一旦有有效的消息移动到Outbox,就会调用系统发送代码。不通过移动消息,你也可以使用IMessage::SubmitMessage提交Message。
#actionman 发表于2006-09-12 09:18:00  IP: 61.151.255.*
如何知道是移到Outbox了, 看哪个变量, 我感觉移到其他box里也一样收到notify. 不知道区别在哪。
#yzx0023 发表于2006-09-12 11:30:00  IP: 218.108.41.*
To actionman: 在OBJECT_NOTIFICATION结构里面有个叫lpParentID的成员,他记录了消息的父亲(即Box)的Entry ID,它是一个全局标识,你可以事先取的Outbox的Entry ID,然后和它做memcmp,关于如何取的Folder的Entry ID,前面的文章应该有所提到。
#actionman 发表于2006-09-12 20:01:00  IP: 61.151.255.*
谢谢!, 我可以看到Entry ID了, 但还有几个问题
1, 如发送成功了, 如何通知, 以便把message移动到已发邮件夹里
2, 如发送不成功, 如何通知系统重发
3, 在发送时, 又有邮件到了OutBox, 系统如何应对,


#yzx0023 发表于2006-09-12 21:43:00  IP: 220.191.35.*
To actionman:
1. 不知道发送动作是谁做的?你的程序还是系统?一般来说,系统已经包装好了这样的操作,如果用户在mail setting里面设置了保存已发邮件,那么SMS程序在发送成功后会自动保存到已发邮箱那里。
2. 如果发送失败想再次发送,可以调用IMessage::SubmitMessage
3. 系统的默认实现不是很了解,但是一般来说,都会有收发队列。
#swordsmile 发表于2006-12-25 15:32:57  IP:
请问如何得到Outlook-Email的store呢?根据DisplayName遍历我发现只有“SMS”,“MMS”,和“ActiveSync”3个store啊。麻烦告诉一下,非常感谢。
#yzx0023 发表于2006-12-26 21:34:04  IP: 220.191.115.*
To swordsmile:ActiveSync 就是OutlookEmail的store
#hdw191 发表于2007-01-04 15:00:28  IP: 219.136.128.*
OK,今天先写到这里,下篇将继续讨论IMAPIAdviseSink,主要是讲如何在OnNotify中取得被改变的Message对象。


无聊客, 你上面说的这一个下一篇什么时候写啊, 等着看呢~~ 呵呵

#willing007 发表于2007-08-22 13:50:32  IP: 219.142.122.*
无聊客:你好,我最近在删除一条短信的时候,Onnotify有时同时接收到的消息fnevObjectDeleted 和fnevObjectmove,而有时候仅接收到fnevObjectmove消息,能否解释一下。谢谢
#hans 发表于2008-09-11 17:26:12  IP: 116.232.56.*
老大,指条明路吧~

如何在OnNotify中取得被改变的Message对象?

发表评论  


登录
Csdn Blog version 3.1a
Copyright © 无聊客