访问Windows地址簿






4.69/5 (23投票s)
2002年12月22日
5分钟阅读

238440

2447
访问WAB的类。
引言
在我发布了第一个免费软件产品 QuickE 后,收到了大量请求,希望该应用程序能与用户在 Windows 通讯簿中的地址簿集成。在 Windows XP 上,您可以通过单击“开始”->“程序”->“附件”->“[单击] 通讯簿”找到此应用程序。我曾惊讶于有人在使用 Windows 通讯簿,因为我天真地认为每个人都使用 Outlook,或者至少使用 Outlook Express(因为后者至少是免费的),但令我惊讶的是,很多人只是使用 Windows 中自带的普通 Windows 通讯簿应用程序,如果您也使用 Outlook Express,您会发现通讯簿中填充了与 Outlook Express 中相同的地址。当我开始这项任务时,我做的第一件事就是将 WAB(Windows 通讯簿)输入我的 MSDN 搜索工具中,令我惊讶的是,返回给我的信息量非常少。我编写了这个类,以便其他人至少有一个起点来访问和使用 WAB。希望您发现源代码有用。
系统要求
此代码是用非托管 C++ 和 Win XP Professional 在 Visual Studio.NET 中编写和测试的。Tony R. 使用 Visual C++ 6 测试了此代码,并成功运行。如果其他人能在其他平台上运行此代码,请告知我,以便我在此处发布,那将是极好的。在确认此类别能在其他开发环境和操作系统上运行之前,我将仅列出我亲自测试过的内容。
访问 WAB
要访问 WAB,您必须首先加载 wab32.dll 库并获取 WAB 打开的地址,这还会为您提供指向 IAdrBook
和 IWABObject
接口的指针。下面是我如何进行此调用的代码片段。
//We're safe the module was initialzised let's do what we need to do ssWABOpen = (fWABOpen)GetProcAddress(hModule, "WABOpen"); //If not successful throw an error throw the value = 2 if (ssWABOpen == NULL) return 2; //It is successful call it HRESULT hr = (ssWABOpen)(&lpAddrBook, &lpWABObject, NULL, 0);
ssWABOpen
是 typedef
到 WABOpen
函数。在我编写此代码时遇到的一件事是,当您 typedef
此函数时,必须将调用机制声明为 WINAPI,否则在编译时会出现不匹配错误。
在此之后,我将调用对象的 LoadEmails()
函数。这个私有函数从 InitAddrBook
函数内部调用,将电子邮件加载到 STL::vector
对象中的对象 UDT 中。我选择这种方式,主要是因为我对这方面不太了解,我的地址簿大约有 20 个名字,这种方法不会占用太多系统资源。如果这对其他人不起作用,我将更改为更友好的系统资源的方法。
在 LoadEmails()
函数内部,所有从 WAB 到我的 UDT 向量的电子邮件提取都在这里进行。您可以修改或更改此内容,使其更适合您的特定用途。或者,将信息提取到比我创建的 UDT 更实用的 UDT 中。
用法和特殊功能
为了给您提供使用该类的基础,以下是我目前在应用程序 beta 版本中如何使用该类的。在主对话框类中,我声明了一个 CWinAddrBook
类的私有成员变量。然后,我在对话框类的 OnInitDialog()
函数中初始化此变量,通过调用 object.InitAddrBook
成员方法。这做了两件事:首先,它加载 wab32.dll,然后,从中检索 WABOpen()
函数的地址。
为了在发布前测试此类别而不必构建其自己的应用程序容器,我创建了成员方法 TestAddr()
。这基本上是在您初始化后,将 vector 的内容输出(TRACE),同时在调试模式下运行到 output 窗口,然后通过回车换行符对输出进行分隔。这样,您可以确保您的向量中确实有内容,并且可以查看输出与您的地址簿进行比较,以确保所有信息都正确传输。
请求评论/困境
在创建此类别时,我遇到了一些奇怪的事情,也许有人能阐明一下。首先让我措手不及的是,我尝试只包含 wabapi.h,而实际上只包含 wab.h 更好。根据界面帮助部分列出的内容,我看到的只是 WABAPI,有一段时间我无法使其编译。
当我第一次将其编译到我的代码中时,我不断收到一个
error C2371: 'WCHAR' redfinition; different basic types
在 wabdefs.h 中,该文件在您指定 wab.h 时会被包含。我使用的解决方法是进入这个文件,在第 77 行左右,我做了这个修改,以便我的代码能够编译。我不知道为什么我必须这样做,也不知道这样做是否正确,但它确实奏效了。如果有人知道这是什么意思,我将非常感激知道它为什么会这样。
#if !defined(UNIX) && !defined(WIN16) && !defined(WIN32)
LoadEmails()
以前是一个独立的函数,在 InitAddr()
之后调用,但我总是在 OnInitDialog
函数中收到一个未处理的异常。在移除对 LoadEmails
的公共函数调用,并将其作为 InitAddr()
内部调用的私有函数后,它就能正常工作了。
贡献者
不是 MSDN!开玩笑。大多数贡献者都包含在头文件注释中。我还会在这里包含 Hirosh 的文章 使用内存映射文件从地址簿中提取电子邮件 ID,另一位作者是匿名的。我从一个朋友那里得到了代码片段,他说他在网上找到的,我将其按照接收到的方式包含在下载文件中。但是,如果有人知道作者的姓名或网址,请告诉我,以便我给予他/她适当的荣誉。
Tony R. 测试了 Visual C++ 6 中的代码,并发现了许多其他错误。
修订
- 2003/1/2:更新了代码并更改了提取过程,以将信息提取到单独的区域,而不是反复将所有地址信息提取到姓名字段。更改了用于存储地址的结构,使用
basic_string
而不是固定大小的字符数组,以避免我遇到的缓冲区溢出问题。