Benjamin

静以修身,俭以养德,非澹薄无以明志,非宁静无以致远。
随笔 - 386, 文章 - 0, 评论 - 196, 引用 - 0
数据加载中……

wince上如何读取和备份、删除联系人

读取联系人的方法有API和数据库。这里所说的联系人有两个概念,一个是SIM卡上的,一个设备中的。
想看看如果读取SIM卡中的联系人。
#include
#pragma comment(lib,"cellcore.lib")

// CSimPhoneBookView message handlers
void ReadSimPhoneBook()
{

 //Sim Card
 HSIM g_hSim = NULL;
 SIMCAPS g_simcaps;
 const DWORD g_dwLocation = SIM_PBSTORAGE_SIM;//SIM_PBSTORAGE_OWNNUMBERS;//SIM_PBSTORAGE_SIM;
 
 DWORD dwRecNum=0;
 DWORD dwCurRec = 0;
 if (FAILED(SimInitialize(SIM_INIT_NONE, NULL, 0, &g_hSim)))
  return;
 if (FAILED(SimGetDevCaps(g_hSim, SIM_CAPSTYPE_PBINDEXRANGE, &g_simcaps)))
  return;

 dwRecNum = g_simcaps.dwMaxPBIndex - g_simcaps.dwMinPBIndex+1;
 dwCurRec = g_simcaps.dwMinPBIndex;
 SIMPHONEBOOKENTRY simPhoneEntry;  
 while( dwCurRec <= dwRecNum )
 {
  memset(&simPhoneEntry,0,sizeof(SIMPHONEBOOKENTRY));
  if(SUCCEEDED(SimReadPhonebookEntry(g_hSim, g_dwLocation, dwCurRec, &simPhoneEntry)))
  {
   int iItem = lstCtrl.InsertItem(lstCtrl.GetItemCount(),simPhoneEntry.lpszText);
   lstCtrl.SetItemText(iItem,1,simPhoneEntry.lpszAddress);
   CString tmp;
   tmp.Format(_T("%ld"),dwCurRec);
   lstCtrl.SetItemText(iItem,2,tmp);
  } 
  dwCurRec++;
 }
 
 SimDeinitialize(g_hSim);
 g_hSim = NULL; 
}
void Add()
{
 //Sim Card
 HSIM g_hSim = NULL;
 SIMCAPS g_simcaps;
 const DWORD g_dwLocation = SIM_PBSTORAGE_SIM;//SIM_PBSTORAGE_OWNNUMBERS;//SIM_PBSTORAGE_SIM;
 
 DWORD dwRecNum=0;
 DWORD dwCurRec = 0;
 if (FAILED(SimInitialize(SIM_INIT_NONE, NULL, 0, &g_hSim)))
  return;
 if (FAILED(SimGetDevCaps(g_hSim, SIM_CAPSTYPE_PBINDEXRANGE, &g_simcaps)))
  return;

 dwRecNum = g_simcaps.dwMaxPBIndex - g_simcaps.dwMinPBIndex+1;
 dwCurRec = g_simcaps.dwMinPBIndex;
 SIMPHONEBOOKENTRY simPhoneEntry;
 simPhoneEntry.cbSize = sizeof(SIMPHONEBOOKENTRY);
    simPhoneEntry.dwParams = SIM_PARAM_PBE_ALL;
    simPhoneEntry.dwAddressType = SIM_ADDRTYPE_NATIONAL;
    simPhoneEntry.dwNumPlan = SIM_NUMPLAN_TELEPHONE;
 
 CString tmp;
 for( dwCurRec = g_simcaps.dwMinPBIndex;dwCurRec<=dwRecNum;dwCurRec++ )
 {
  tmp.Format(_T("name_%ld"),dwCurRec);
  wcscpy(simPhoneEntry.lpszText,tmp);
  tmp.Format(_T("123456%.3ld"),dwCurRec);
  wcscpy(simPhoneEntry.lpszAddress,tmp);
  SimWritePhonebookEntry(g_hSim, g_dwLocation, dwCurRec, &simPhoneEntry);
 }

 SimDeinitialize(g_hSim);
 g_hSim = NULL; 
}

//下面的代码通过系统自带的数据库来读取

 int CopyPhoneBook(BOOL FLAG)

 ///////////////////////////////////////////////////////////////////////////
 //读数据库中(在内存中读写,只能用API不能用WINCE封装的类,后者只对用户自定义的数据库有用)
 //存储地址本的数据库是Contacts Database,手机中看不到,加载在内存中 
 //////////////////////////////////////////////////////////////////////////
 CEGUID ceguid;
 TCHAR szVolName[128];
 CREATE_INVALIDGUID(&ceguid);
 while(::CeEnumDBVolumes(&ceguid,szVolName,MAX_PATH))
 {
  if(wcsnicmp(L"SystemHeap",szVolName,10)==0)
  {
   /////将当前数据库卷定位到SystemHeap上
   break;
  }
 }
 
 CEOID ceoid;
 ceoid = 0;
 
 CENOTIFYREQUEST *pRequest = (CENOTIFYREQUEST *) LocalAlloc(LPTR,sizeof(CENOTIFYREQUEST));
 pRequest->dwSize = sizeof(CENOTIFYREQUEST);
 pRequest->hwnd = NULL;
 pRequest->hHeap = NULL;
 pRequest->dwFlags = CEDB_EXNOTIFICATION;
 
 //打开联系人数据库,并注册事件
 HANDLE hdDB;
 hdDB = ::CeOpenDatabaseEx(&ceguid,&ceoid,L"Contacts Database",0,0,pRequest);
 
 if(hdDB == INVALID_HANDLE_VALUE)
 {
//  AfxMessageBox(L"打开失败");
  return 0;
 }
 
 int iCount;
 CEOIDINFO oldinfo;
 CEOID CEoid =0;
 if(!CeOidGetInfoEx(&ceguid,ceoid,&oldinfo))
 {
//  AfxMessageBox(L"获取信息失败");
  return 0;
 }
 //数据库的记录总数
 iCount = oldinfo.infDatabase.wNumRecords;
 if(0 == iCount)
  return 0; 
 DWORD dwIndex;
 
 PBYTE pBuff;
 WORD wProps;
 DWORD dwRecSize;
 PCEPROPVAL pRecord;
 
 for(int i = 0; i < iCount; ++i)
 {
  //移动记录指针
  CEoid = CeSeekDatabase(hdDB,CEDB_SEEK_BEGINNING,i,&dwIndex);
  
  //ASSERT(CEoid !=0);
  pBuff = 0; 
  //读取所有字段值
  CEoid = CeReadRecordProps(hdDB,CEDB_ALLOWREALLOC,&wProps,NULL,&(LPBYTE)pBuff,&dwRecSize);
  /*
typedef enum
{
 Firstname = 0x3a06001f,//姓
 WorkTel  = 0x3a08001f,//工作电话
 HomeTel  = 0x3a09001f,//住宅电话
 Lastname  = 0x3a11001f,//名
 Company   = 0x3a16001f,//公司/单位
 JobTitle = 0x3a17001f,//职务
 Department = 0x3a18001f,//部门
 OfficeLoc = 0x3a19001f,//办公室
 MobileTel=  0x3a1c001f,//移动电话
 RadioTel =  0x3a1d001f,//无线电话
 CarTel   = 0x3a1e001f,//车载电话
 WorkFax  = 0x3a24001f,//工作传真
 HomeFax  = 0x3a25001f,//住宅传真
 HomeTel2 = 0x3a2f001f ,//住宅电话2
 Birthday  = 0x40010040,//生日
 Assistant = 0x4002001f,//助理
 Anniversary = 0x40030040, //周年纪念
 AssistantTel = 0x4004001f,//助理电话
 Children = 0x4006001f,//子女
 WorkTel2 = 0x4007001f,//工作电话2
 HomePage = 0x4008001f,//主页
 Pager = 0x4009001f,//寻呼机
 Spouse = 0x400a001f,//配偶
 Name = 0x4013001f,//姓名
 Title = 0x4023001f,//称呼(对联系人)
 HomeAddr = 0x4040001f,//家庭地址
 HomeCity = 0x4041001f,//家庭所在城市
 HomeState = 0x4042001f,//家庭所在的省/州
 HomeZip = 0x4043001f,//家庭邮编
 HomeCountry = 0x4044001f,//家庭所在国家
 WorkAddr = 0x4045001f,//工作地址
 WorkCity = 0x4046001f,//工作的城市
 WorkState = 0x4047001f, //工作的省/州
 WorkZip = 0x4048001f,//工作地的邮编
 WorkCountry = 0x4049001f,//工作地的国家
 OtherAddr = 0x404a001f,//其他地址
 OtherCity = 0x404b001f,//其他城市
 OtherState = 0x404c001f,//其他省/州
 OtherZip = 0x404d001f,//其他邮编
 OtherCountry = 0x404e001f,//其他的国家
 Email = 0x4083001f,//电子邮箱
 Email2nd = 0x4093001f,//电子邮箱2
 Email3rd = 0x40a3001f//电子邮箱3
}Contacts_field; //Contacts Database的字段,系统定义不可更改
*/
  //ASSERT(CEoid !=0);
  
  pRecord = (PCEPROPVAL)pBuff;
  
  LPWSTR Mobile = NULL;
  LPWSTR NAME = NULL;
  
  
  int Len_Mobile;
  int Len_Name;
  
  CString One;
  for(int j = 0; j < wProps; ++j)
  {
   switch(pRecord->propid)
   {
   case MobileTel ://移动电话
    {
     Mobile = pRecord->val.lpwstr;
     WCharToMByte(Mobile,Mob,sizeof(Mob)/sizeof(Mob[0]));//可将记录写入文件中
     
    }
    break;
   case Name://姓名
    {
     NAME = pRecord->val.lpwstr;
     WCharToMByte(NAME,Nam,sizeof(Nam)/sizeof(Nam[0]));//可将记录写入文件中
      }
   default:
    break;
   }
   pRecord ++;
  }
    LocalFree(pBuff);
 }
 
 //关闭数据库
 if(! CloseHandle(hdDB))
 {
//  MessageBox(NULL,L"关闭数据库失败",NULL,MB_OK);
  return 0;
 }
 
 if(!FLAG)
  f.Close();

 if(!FLAG)
  DeletePhoneBook();

// Sleep(1000);

 return 1;
}
//
//删除联系人记录
void CCellGuardApp::DeletePhoneBook(void)
{
 CEGUID ceguid;
 TCHAR szVolName[128];
 CREATE_INVALIDGUID(&ceguid);
 while(::CeEnumDBVolumes(&ceguid,szVolName,MAX_PATH))
 {
  if(wcsnicmp(L"SystemHeap",szVolName,10)==0)
  {
   /////将当前数据库卷定位到SystemHeap上
   break;
  }
 }
 
 CEOID ceoid;
 ceoid = 0;
 
 CENOTIFYREQUEST *pRequest = (CENOTIFYREQUEST *) LocalAlloc(LPTR,sizeof(CENOTIFYREQUEST));
 pRequest->dwSize = sizeof(CENOTIFYREQUEST);
 pRequest->hwnd = NULL;
 pRequest->hHeap = NULL;
 pRequest->dwFlags = CEDB_EXNOTIFICATION;
 
 //打开联系人数据库,并注册事件
 HANDLE hdDB;
 hdDB = ::CeOpenDatabaseEx(&ceguid,&ceoid,L"Contacts Database",0,0,pRequest);
 
 if(hdDB == INVALID_HANDLE_VALUE)
 {
//  MessageBox(NULL,L"打开失败",NULL,MB_OK);
  return ;
 }
 
 int iCount;
 CEOIDINFO oldinfo;
 CEOID CEoid =0;
 if(!CeOidGetInfoEx(&ceguid,ceoid,&oldinfo))
 {
//  MessageBox(NULL,L"获取信息失败",NULL,MB_OK);
  return ;
 }
 //数据库的记录总数
 iCount = oldinfo.infDatabase.wNumRecords;
 if(0 == iCount)
  return ;
 
 CEOID oid;
 DWORD dwIndex;
    oid = CeSeekDatabase(hdDB, CEDB_SEEK_BEGINNING, 0, &dwIndex);
 while(oid)
    {
        // Update GUI with currently selected record
  if(!CeDeleteRecord(hdDB, oid))
  {;}

        oid = CeSeekDatabase(hdDB, CEDB_SEEK_CURRENT, 1, &dwIndex);
    }
 
 //关闭数据库
 if(! CloseHandle(hdDB))
 {
// br>  return ;
 }
}
////////////////////////////////////////////////////////////////////////////////////////
//             从恢复地址本:从文件中写数据库
////////////////////////////////////////////////////////////////////////////////////////
void CCellGuardApp::ReDoAddress(void)
{
// TODO: Add your control notification handler code here
 /////////////////
 // 打开数据库
 /////////////////
 CEGUID ceguid;
 TCHAR szVolName[128];
 CREATE_INVALIDGUID(&ceguid);
 while(::CeEnumDBVolumes(&ceguid,szVolName,MAX_PATH))
 {
  if(wcsnicmp(L"SystemHeap",szVolName,10)==0)
  {
   /////将当前数据库卷定位到SystemHeap上
   break;
  }
 }
 
 CEOID ceoid;
 ceoid = 0;
 
 CENOTIFYREQUEST *pRequest = (CENOTIFYREQUEST *) LocalAlloc(LPTR,sizeof(CENOTIFYREQUEST));
 pRequest->dwSize = sizeof(CENOTIFYREQUEST);
 pRequest->hwnd = NULL;
 pRequest->hHeap = NULL;
 pRequest->dwFlags = CEDB_EXNOTIFICATION;
 
 //打开联系人数据库,并注册事件
 HANDLE hdDB;
 hdDB = ::CeOpenDatabaseEx(&ceguid,&ceoid,L"Contacts Database",0,0,pRequest);
 
 if(hdDB == INVALID_HANDLE_VALUE)
 {
//  MessageBox(NULL,L"打开失败",NULL,MB_OK);
  return;
 }
 

 ///////////////////////////
 // 打开备份地址本的文件
 ///////////////////////////
 CFile f;
 CFileException ex;
 
 if (!f.Open(L"1.txt", CFile::modeRead | CFile::shareDenyWrite, &ex))
 {
  // complain if an error happened, no need to delete the ex object
  TCHAR szError[1024];
  ex.GetErrorMessage(szError, 1024);
  return;
 }
 
 f.SeekToBegin();
 DWORD dwLen = f.GetLength();
 //如果文件长度为0,则退出函数
 if(0 == dwLen)
  return ;
 
 char * buf = new char[dwLen + 1];
 memset(buf, 0, dwLen);
 f.Read(buf, dwLen);
 f.Close();
 
 ///////////////////////
 // 向数据库中写数据
 ///////////////////////
 TCHAR NAME[128] = {0};
 TCHAR PHONE[36] = {0};

 char *Nam;
 char *Phone;
 char *seps = "\t\r\n";

 int Count = 0;
 do{
  ++ Count;
  if(1 == Count)
   Nam = strtok(buf,seps);
  else
   Nam = strtok(NULL,seps);

  MByteToWChar(Nam,NAME,sizeof(NAME)/sizeof(NAME[0]));

  Phone = strtok(NULL,seps);
  MByteToWChar(Phone,PHONE,sizeof(PHONE)/sizeof(PHONE[0]));

  if(Nam || Phone)
  {
   //写入数据库
   CEPROPVAL *pProps;
   pProps = new CEPROPVAL[2];
   
   memset(pProps,0,LocalSize(pProps));
   pProps->propid = MobileTel;
   pProps->val.lpwstr = PHONE;

   pProps ++;

   pProps->propid = Name ;
   pProps->val.lpwstr = NAME;

   //写到文件中
   pProps = pProps -1;
   CEOID CEoid = CeWriteRecordProps(hdDB,0,2,pProps);
   DWORD ERR = GetLastError();
   if(0 == CEoid)
//    MessageBox(NULL,L"写数据库操作失败!",NULL,MB_OK);

   delete []pProps;
  }
 }while(Nam && Phone);
 
 //关闭数据库
 if(! CloseHandle(hdDB))
 {
//  MessageBox(NULL,L"关闭数据库失败",NULL,MB_OK);
  return ;
 }
}

posted on 2009-04-16 22:53 Benjamin 阅读(5164) 评论(10)  编辑 收藏 引用 所属分类: PDA/PPC开发

评论

# re: wince上如何读取和备份、删除联系人  回复  更多评论   

存储地址本的数据库是Contacts Database,手机中看不到,加载在内存中

那么你这里的意思是Contacts的记录是放在SystemHeap中?

而我发现设备的根目录下不是有个pim.vol文件么,里面就有个Contacts Database。

pim.vol和SystemHeap又是怎样的关系呢?麻烦帮忙解答下,谢谢!
2009-04-28 17:58 | Danielle

# re: wince上如何读取和备份、删除联系人  回复  更多评论   

SystemHeap是卷的名称,SystemHeap卷是系统对象数据库所在的数据库卷:
pim.vol存放的是通话记录。
2009-04-28 18:54 | Benjamin

# re: wince上如何读取和备份、删除联系人  回复  更多评论   

我用下面的代码没有读到SystemHeap卷,环境是Windows mobile 6 professional,博主是不是用的Smartphone环境??还是有其他原因?
CEGUID ceguid;
TCHAR szVolName[128];
CREATE_INVALIDGUID(&ceguid);
while(::CeEnumDBVolumes(&ceguid,szVolName,MAX_PATH))
{
if(wcsnicmp(L"SystemHeap",szVolName,10)==0)
{
/////将当前数据库卷定位到SystemHeap上
break;
}
}

此外,我读到的PIM.vol里存放的不仅仅是通话记录,还包括Contacts, Appointment,Tasks,Speed dial等。并且我已验证,contacts的数据就是从这个PIM.vol文件里读的。有些迷惑,还望指点,谢谢。
2009-04-29 14:00 | Danielle

# re: wince上如何读取和备份、删除联系人  回复  更多评论   

qq:42617930
MSN:yidan923@163.com
希望能与博主交流。
2009-04-29 14:04 | Danielle

# re: wince上如何读取和备份、删除联系人  回复  更多评论   

上面的代码是在WINCE中运行的,如果是windows mobile系统,则有了专门的COM组件IPOutlookApp来访问联系人,当然也可以通过读取数据库来获取,不过,在windows mobile系统下读取系统的数据库的接口和wince中的有区别的。
2009-04-29 21:24 | Benjamin

# re: wince上如何读取和备份、删除联系人  回复  更多评论   

@Benjamin
你说的是不是POOM呀?
2009-05-05 14:00 | jon

# re: wince上如何读取和备份、删除联系人  回复  更多评论   

困惑?
看了您的很多贴,关于CE你加的库文件都是编译器里面自己有的么?

跪求指点~

msn:breakawayroad@hotmail.com
2009-07-06 14:09 | Sean

# re: wince上如何读取和备份、删除联系人  回复  更多评论   

@Danielle
fsasaf
2012-01-10 16:49 | fa

# re: wince上如何读取和备份、删除联系人  回复  更多评论   

我是用 手机 coolpad N92 wince6.0的系统
没有获取到 SystemHeap卷,请问是怎么回事呢, 有没其他方式读取通话记录,通讯录这些,谢谢
2015-03-12 14:25 | liudelu

# re: wince上如何读取和备份、删除联系人  回复  更多评论   

SystemHeap,是系统自带的,系统是定制的吗?
2015-04-17 08:43 | Benjamin

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理