不迎不送,来去自便,无茶无酒,谈笑随缘

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  74 随笔 :: 0 文章 :: 0 评论 :: 0 引用

公告

CEMAPI实战攻略(三)——操作信箱中的短信息(上)

by 吴春雷

QQ:819543772

Email:wuchunlei@163.com

三.操作信箱中的短信息

1.       Windows mobile中短消息的组成

用过的Windows Mobile平台设备的朋友在第一次发送的短信的时候或多或少都会有些困惑,尤其是使用Windows Mobile 2003以前版本的朋友,发短信的UI上不但有填写目的号码和正文的地方,还有填写主题,CC甚至BCC的位置,搞得用户不知如何是好。为什么会有这些内容前面实际上已经提到过了。WM系统中邮件和短消息属于一个系统,微软为了开发方便将二者使用了相同的架构和接口,因此才会有短消息中存在CCBCC这样的事情出现。虽然从WM5.0以后的版本开始,主题,CCBCC等东西已经不见了,但是为了后面方便阐述解析原始短信息部分内容,这里简单的说一下短信的结构组成。

CCBCC这些内容是发送短信中不需要的,填写了也没有什么效果。但是主题(subject)如果填写了是会对短信内容产生影响的。MSDN上介绍,如果发送短信的时候在主题和正文(Body)中都填写了内容,那么发送时,系统会在主题的内容后增加一个换行符,然后在把正文添加到后面作为短信真正的正文发送出去。注意WM中的换行符是\n而不是\r\n。除了主题和正文以外,一条短息还包括发送时间,接收时间,发送方号码,接受方号码等属性组成。在某一条具体信息之中这些属性不一定同时存在,对于不同具体信箱(Folder)中的短信息,拥有不同的属性。例如:收件箱中的短信,只有正文、发送方号码、发送时间这几个属性。

2.       IMessage接口

          前面对短信的结构做了一个简要的了解,现在要介绍一个与短信相关的非常重要的接口,IMessage接口。该接口直接继承自IMAPIProp,有IMAPIProp间接继承自IUnknow接口,同样属于COM对象。接口中封装了与短信相关的基本操作,常用的方法,例如Get/SetPropsSubMessageSaveChange等方法是值得大家去特别注意的,这些方法的用法,后面会提到。

3.       SizedSPropTagArray

       上一部分中我们已经介绍过SizedSPropTagArray宏以及用它动态生成结构体类型的方法,这里再强调一下,这个宏在cemapi中非常重要,希望大家能够关注。关于这个宏的使用方法,请参见上一部分的内容。

4.       从具体信箱中获取一条原始短消息

          上一部分中已经详细的讨论了如何建立与短信邮件系统的会话(Session),如何获取短信仓库(MsgStore)以及如何与具体的信箱(Folder)进行连接。我们先来简单回顾一下,首先利用MAPILogonEx函数建立与短信邮件系统的会话,然后利用IMAPISession接口的对象获取所有消息(邮件)仓库(MsgStore),遍历这些仓库,根据PR_DISPLAY_NAME属性的值获取短信所对应的短信仓库对象。然后根据具体信箱对应的参数获取指向具体信箱的对象(Folder)

        有了具体的信箱以后,下面需要做的就是要从该信箱中获取一条原始短消息了,原始短消息由Imessage接口对应的对象表示。前面说过,Cemapi中无论是短信(邮件)仓库MsgStore,还是具体信箱(Folder)均是由表格的形式表示的,Folder中的短信自然也不例外。我们可以通过GetContentsTable方法来获取信息对应的表格对象IMAPITable。如果大家忘记了,可以返回上一部分再看一下。GetContentsTable方法声明如下:

                   HRESULT IMAPIFolder::GetContentsTable(ULONG,IMAPITable **);

      方法的返回值用于判断方法是否执行正确。参数列表:

ULONG:很抱歉,这个参数我没有看到过相关的介绍,在我们的应用中赋值为0是可以正常工作的。

IMAPITable **:用于返回短信列表对应的表结构。

            

我认为Cemapi中有一个原则(你可以不这么认为),只要出现了IMAPITable接口的对象,就需要采用SizePropTagArray这个宏来声明一个动态结构体,并且调用SetColumns告诉IMAPITable接口对象,列表中的行记录的组织结构。现在我们需要获取行记录中的ENTRYID,然后用这个ENTRYIDFolder中获取对应的短信息对象。

        SizedSPropTagArray(1, Columns) =    //动态生成结构体对象,只获取Entry ID属性

        {

            1,

            PR_ENTRYID 

};

还记得这么声明的意义吗?我们声明了一个动态结构体变量Columns,该结构体中的ULONG值为1(表示数组元素数量),ULONG数组共一个元素,名为PR_ENTRYID。有了这个结构体以后,采用SetColumns方法就可以对表格中行记录结构进行设置了。源代码如下:

              IMAPITable  *m_pTable = NULL;

m_pFolder->GetContentsTable(0, &m_pTable);      //获取该Box下的短信行记录列表

hr = m_pTable->SetColumns((LPSPropTagArray)&Columns, 0);    //设置列格式

行记录结构设置完毕以后,与获取MsgStore对象类似,使用QueryRows方法就可以获取该表中所有的行记录了。获取每一行的ENTRYID属性,然后使用IMAPIFolder中的OpenEntry方法(很熟悉吧,没错,就是与获取MsgStoreImsgStore中的同名方法相同)来获取EntryId对应的短消息了。

获取原始短消息的代码如下:

        LPMAPITABLE  m_pTable = NULL;

        LPSRowSet m_pRows = NULL;

        HRESULT hr;

       

        SizedSPropTagArray(1, Columns) =    //动态生成结构体对象,只获取Entry ID属性

        {

            1,

            PR_ENTRYID 

        };

 

        m_pFolder->GetContentsTable(0, &m_pTable);      //获取该Box下的内容列表

        hr = m_pTable->SetColumns((LPSPropTagArray)&Columns, 0);    //设置列记录结构

 

        if(FAILED(hr))

        {

            //异常处理

        }

 

        ULONG ulRowCount=0;

        ULONG i=0;

 

        m_pTable->GetRowCount(0,&ulRowCount);           //获取列表中行记录总数

       

        while(!FAILED(m_pTable->QueryRows(1, 0, &m_pRows)))

        {

            if(i==ulRowCount) break;         //如果已经遍历完毕

            else i++;

 

            IMessage *m_pMsg = NULL;

            ULONG ulMesageType;

            //通过OpenEntry获取IMessage对象

            hr=m_pFolder->OpenEntry( m_pRows->aRow[0].lpProps[0].Value.bin.cb,

             (LPENTRYID)m_pRows->aRow[0].lpProps[0].Value.bin.lpb,

             NULL,

             MAPI_BEST_ACCESS,

             &ulMesageType,

             (LPUNKNOWN*)&m_pMsg);

 

            if(!FAILED(hr) && NULL!=m_pMsg)     //取到了消息

            {

                //取到了原始消息

            }

 

                if(m_pRows)

                {      

                    FreemProws(m_pRows);        //释放行

                    m_pRows=NULL;

                }

        }

 

        if(m_pTable)

        {

            m_pTable->Release();        //释放表结构

            m_pTable=NULL;

}

    5.释放IMessage对象.

        使用IMessage::Release()方法,可以安全的释放该对象。代码如下:

m_pMsg->Release();

posted on 2009-03-09 19:55 wude 阅读(...) 评论(...) 编辑 收藏