从Outlook中获得反馈信息

翻译|其它|编辑:郝浩|2004-07-23 09:33:00.000|阅读 2373 次

概述:

# 界面/图表报表/文档/IDE等千款热门软控件火热销售中 >>


用 BindEvents 从 Outlook 2000 获得反馈信息

关于 Microsoft Office 程序包的最棒的一件事情是:任务自动化,例如建立邮件、打印文档以及从其它应用程序中使用OLE 自动化是多么的容易。我已经在多个应用程序中广泛的使用了这个技术,例如让用户直接在他们的Outlook 文件夹中建立e-mails、约会、任务和备注。但是,直到 VFPCOM 插件发布以前, VFP 程序员只能享受一半的好处。我们可以通过设置参数和调用方法来进行操作,但我们不能对应用程序服务器的事件做出反应。 

绑定并回送 
VFPCOM 工具 (从 http://msdn.microsoft.com/vfoxpro/downloads/updates.asp 下载)提供了编程访问 OLE 自动化服务器引发的事件的能力(它还提供了一个填充和读入 ADO 记录集的方法,但那一点可以用另一篇文章专述) 。 

为了绑定到 OLE 自动化服务器的事件, VFPCOM 工具最重要的方法是 ExportEvents(),BindEvents(), 和 UnBindEvents()。 ExportEvents() 建立一个非可视模板类,这个类的方法的名称与 OLE 自动化服务器的事件名相同。BindEvents() 在一个基于模板类的对象实例和 OLE 自动化服务器之间建立一个连接。UnBindEvents 释放这个连接。 

ExportEvents() 
需要一个其方法名与 OLE 自动化服务对外提供的事件名相同的 VFP 类,以当一个服务器事件触发时使程序员有地方可以放将要运行的代码。虽然手动建立那么一个类是可能的,不过 VFPCOM 提供了一个生成非可视类的方法。为了生成这个模板,给 ExportEvents 传递一个可用的 OLE 自动化服务器的对象变量和一个文件名。例如,如果你安装了 Outlook 2000,运行在清单 1 中显示的代码将生成清单 2 中的模板。稍后我将讨论在代码中的占位符部分(就是“* Add user code here”部分)将会有什么东西。(在这篇文章中所有的代码都可以从附带的下载文件中找到) 

清单 1. 创建一个可绑定模板. 

#DEFINE VFPCOM_CLSID "VFPCOM.COMUTIL" 
#DEFINE OUTLOOK_CLSID "OUTLOOK.APPLICATION" 

local loVFPCOM, loOutlook 
loVFPCOM = create(VFPCOM_CLSID) 
loOutlook = create(OUTLOOK_CLSID) 

loVFPCOM.ExportEvents(loOutlook, ; 
'Outlook_Events.prg') 

清单 2. 运行清单 1 中的代码的结果-一个 Outlook 的可绑定模板. 

DEFINE CLASS ApplicationEvents AS custom 

PROCEDURE ItemSend(Item,Cancel) 
* Add user code here 
ENDPROC 

PROCEDURE NewMail 
* Add user code here 
ENDPROC 

PROCEDURE OptionsPagesAdd(Pages) 
* Add user code here 
ENDPROC 

PROCEDURE Quit 
* Add user code here 
ENDPROC 

PROCEDURE Reminder(Item) 
* Add user code here 
ENDPROC 

PROCEDURE Startup 
* Add user code here 
ENDPROC 

ENDDEFINE 

下一步是给对 OLE 自动化服务器事件的触发做出反应的方法添加一些代码。在清单 3 里,我已经简单的为每个事件显示一个对话框以告诉用户正在发生什么事情 (Okay, 我希望我们继续学习要有一点耐心)。注意我已经重命名了这个类。ExportEvents() 假设了一个调用这个类的好名字,但它没有假设的多好。 

清单 3. 响应 Outlook 事件的代码. 

DEFINE CLASS OutlookApplicationEvents AS custom 

PROCEDURE ItemSend(Item,Cancel) 
MessageBox('用户发送了一个项') 
ENDPROC 

PROCEDURE NewMail 
MessageBox('有新的邮件到达') 
ENDPROC 

PROCEDURE OptionsPagesAdd(Pages) 
MessageBox('添加了选项页') 
ENDPROC 

PROCEDURE Quit 
MessageBox('Outlook 关闭了') 
ENDPROC 

PROCEDURE Reminder(Item) 
MessageBox('提示激活了') 
ENDPROC 

PROCEDURE Startup 
MessageBox('Outlook 启动了') 
ENDPROC 

ENDDEFINE 
BindEvents() 

下一件要做的事情是把 VFP 代码和 OLE 自动化服务器链接起来,以使在自动化服务器中的一个事件触发时运行在 VFP 类中的代码。为了达到这个目的,实例化 OLE 自动化服务器和一个 VFP 类,然后用 VFPCOM 的 BindEvents() 方法把它们链接起来。清单 4 中的代码做了个示范: 

清单 4. 连接 VFP 代码到 Outlook 的事件. 

public goVFPCOM, goOutlook, goLink 
goVFPCOM = create(VFPCOM_CLSID) 
goOutlook = create(OUTLOOK_CLSID) 
goLink = create('OutlookApplicationEvents') 
goVFPCOM.BindEvents(goOutlook, goLink) 

现在,每一次 Outlook 触发在 OutlookApplicationEvents 类的事件列表中的一个事件,相应的 VFP 方法代码也将被运行。在这种情况下,VFP 代码将显示一个关于它的对话框。 

注意我已经声明了三个 public 变量。 这对于只要你需要这个绑定的时候保证它们都在可用范围内是很重要的。这篇文档要警告的是:如果 VFPCOM 对象被释放了而 BindEvents() 还在使用中,将会发生可怕的问题。除了 public 变量还有一个可供选择的方法,例如,你可以把对象变量赋值给一个应用程序对象或者一个表单的的属性。只要在自动化服务器和 VFP 事件之间的连接被要求的期间内,这三个对象都在范围内,就没有关系。要切断在自动化服务器和 VFP 对象之间的连接,释放任何一个或者同时释放连接对象的对象变量,或者像在清单 5 中显示的那样调用 VFPCOM 对象的 UnBindEvents() 方法。 

清单 5. 切断 Outlook 应用程序和 VFP 事件之间的严格的连接. 

goVFPCOM.UnBindEvents(goOutlook, goLink) 
release goVFPCOM, goOutlook, goLink 

示例绑定到 Outlook 的代码 
如果你像我第一次发现这个功能的时候那么激动,你可能渴望看到它在实际情况中被使用。为了描述它的潜能的一小部分,我已经建立了一个允许用户使用他们的 Outlook 2000 界面发送 e-mail 的小表单,它在一个表中准确的记录了发送了什么和发送给谁。像这样一个途径意味着无论是谁发送了 e-mail,它都能被登记在一个中心位置。你与消费者的客户通信将被巩固而不管与消费者交易了多少条花织布。这个表单包含在附带的下载文件中。要运行这个例子: 

1. 已经安装了 Outlook 2000 
2. 已经安装了VFPCOM 工具 
3. 解压缩附带的下载文件到一个新的目录中 
4. 打开 VFP 并用 CD 命令切换路径到你刚建立的目录中 
5. DO FORM ol2kbind.scx 

在图 1 中的表单将显示。象清单 6 显示的那样,这个表单在 init 方法中完成所有必须的事件绑定。注意那里不需要使用由 ExportEvents() 生成的类定义。在这个例子里,我把每一个方法添加到表单本身上面,并直接把表单与 Outlook 的实例相连接。还要注意的是:那个 Outlook 的实例和 VFPCOM 的实例被保存为表单的属性。在对象变量被释放前,destroy 保证连接被切断。 

清单 6. 示例表单的 init() 方法. 

with this 
.oOutlook = create('outlook.application') 
.oVFPCOM = create('VFPCOM.ComUtil') 
.oVFPCOM.BindEvents(.oOutlook, this) 
endwith 

我们的例子的办法是用户可以为在列表中的消费者生成 e-mail 并把它们相应的记录在 items_sent 表中。对可以获得特殊的附加价值的消费者有一个限制条件。只有那些在 customer 表中的 flag 设置为 .T. 的消费者被允许获得 sp_attach 表中列出的项目。 

要开始一封 e-mail,在标各种选择一个消费者然后单击发送 E-Mail 按钮。这将触发表单的 CreateMail 方法,显示在清单 7 中。 

清单 7. 示例表单的 CreateMail() 方法. 

if eof('customer') 
messagebox('请选择一个消费者', ; 
MB_ICONEXCLAMATION, this.caption) 
return .f. 
endif 

WITH THIS 

LOCAL loMessage, loInspector 

loMessage = .oOutlook.createitem(olMailItem) 

loMessage.UserProperties.ADD('CustID', olNumber) 
loMessage.UserProperties('CustID').VALUE = ; 
customer.custid 

loMessage.Recipients.ADD(customer.cust_email) 
loMessage.Recipients.ResolveAll() 
loInspector = loMessage.GetInspector 
loInspector.ACTIVATE() 

ENDWITH 

这个 CreateMail() 方法检查记录指针是否指向一个有效的消费者。然后建立一个 Outlook 邮件数据项并当数据项被发送的时候为操作设置一个包含消费者编号(customer ID)的自定义属性。下一步,它设置收件人的 e-mail 地址并检查它以保证 Outlook 可以解析它。最后,它打开Outlook 默认的编辑表单(被称之为 inspector — 查看在 inspector 上的工具条以获得更多的信息)并把控制权返回给用户。 

用户可以编辑文字并使用一个标准的 Outlook 表单发送他们的信息,就像他们为其他任何 E-mail 所作的那样。玩一会儿这个东西。附上在禁止列表(特殊价格表 List.txt 和试算表 Estimates.txt,包含在附带的下载文件中)中的数据项中的一个。当你准备好了以后,按下发送按钮,Outlook 会触发一个 ItemSend 事件。 

这就是 VFPCOM 连接等待已久的东西!它触发表单的 ItemSend() 方法,显示在清单 8 中。 

清单 8. 示例表单的 ItemSend() 方法. 

lParameters Item, Cancel 

* if there is not a customerID attached to the item, 
* just let it go 
if ! type('Item.UserProperties("CustID").value') = "N" 
return .t. 
endif 

* look up the customerID if it's not there, 
* cancel the send 
if ! seek(Item.UserProperties("CustID").value,'LookupCustomer') 
Cancel = .t. 
Messagebox('客户未找到 - 发送取消', MB_ICONEXCLAMATION, this.caption) 
return .f. 
endif 

local loRecipient, loAttachment, lcSubject, lcFrom, lcTo, lcCC, lcBCC, lcAttachments 
store '' to lcSubject, lcFrom, lcTo, lcCC, lcBCC, ; 
lcAttachments 
lcSubject = item.subject 

* get the from, to , cc and bcc 
for each loRecipient in item.recipients 
do case 
case loRecipient.type = olOriginator 
lcFrom = loRecipient.Name + ' <' + ; 
loRecipient.Address + '>' 
case loRecipient.type = olTo 
lcTo = lcTo + iif(empty(lcTo), '', CR) + ; 
loRecipient.Name + ' <' + ; 
loRecipient.Address + '>' 
case loRecipient.type = olCC 
lcCC = lcCC + iif(empty(lcCC), '', CR) + ; 
loRecipient.Name + ' <' + ; 
loRecipient.Address + '>' 
case loRecipient.type = olBCC 
lcBCC = lcBCC + iif(empty(lcBCC), '', CR) + ; 
loRecipient.Name + ' <' + ; 
loRecipient.Address + '>' 
endcase 
endfor 

if empty(lcFrom) 
lcFrom = item.SenderName 
endif 

* get a list of the attachments 
lcAttachments = '' 
FOR each loAttachment in item.attachments 
* if the customer is not a special pricing customer 
* and the attachment is on the special pricing list 
* inform the user and reject the send 
if (! lookupcustomer.spec_price) and ; 
seek(lower(alltrim(loAttachment.DisplayName)), ; 
'sp_attach') 
cancel = .t. 
messagebox('This customer is not authorised ' + ; 
'to receive special pricing information - ' + ; 
'send cancelled', ; 
MB_ICONEXCLAMATION, this.caption) 
return .f. 
endif 

lcAttachments = lcAttachments + ; 
if(empty(lcAttachments), '', CR) + ; 
loAttachment.DisplayName 

ENDFOR &&* each loAttachment in item.attachments 
if empty(lcAttachments) 
lcAttachments = '(None)' 
endif 

* insert a record of the email into the log 
insert into items_sent ( ; 
custid, ; 
senttime, ; 
addr_from, ; 
addr_to, ; 
addr_cc, ; 
addr_bcc, ; 
msg_body, ; 
att_list ; 
) values ( ; 
Item.UserProperties("CustID").value, ; 
datetime(), ; 
lcFrom, ; 
lcTo, ; 
lcCC, ; 
lcBCC, ; 
item.body, ; 
lcAttachments ; 


* done 

开头的一小部分代码保证发送的数据项就是被表单开始的那个。它检查在 CreateMail() 方法设置的自定义属性是否存在。如果不是,代码假定那个数据项是用其它方法生成的并返回。下一步,这个方法检查在数据项的自定义属性中指定的消费者编号(customer ID)是否有效。如果无效,它将给用户显示一个对话框并通过设置 Cancel 参数为 .F. 来取消发送。注意这并不意味着信件将被放弃,只是不发送而已。用户可以返回到信件中,修改并重新发送它,或者放弃它。 

一旦信件的信任证明已经被检查,发送数据项所需要的信息登记就被获得。收件人信息被保存在local变量中。下一步,代码遍历数据项的收件人集合。如果消费者没有被审定许可获得特殊的附件,那么每一个附件将根据禁止列表被检查。如果检查到一个不合法的附件,用户将被通知,并且发送将被取消。 

最后,如果信件通过了所有的测试,在发送数据项登记中将加入一个带着所有的可用信息的纪录。 

我已经讲过了所有的用这种技术你可以使用的各种功能。要开始的话,所有的邮件数据项的属性都能被读取并写入到 itemsend() 方法,那么你就可以增加或移去收件人,给信件添加一个注脚,附加一个标准文件等等。接着,所有的其它事件也可以使用,所以你可以给它们添加代码来控制各种事情。 

最后,我跳过了 Outlook.Application 对象的事件,它们是许多子对象,每一个都有自己的可以请求利用的事件。 

结论 
VFPCOM 为我们提供了一个额外的方法来对我们可以使用的工具起真正的杠杆作用。尽管这个示例专注于使用 Outlook,提供的这个技术可以与任何 OLE 自动化服务器的表面事件一起使用。前进—粘着它直到它被重创!(Go ahead-bind 'till it hurts.) 

进一步的帮助 
VFPCOM 工具还带着一些部分文档。还有一些有用的在线 KB 文章,并包含在 MSDN 和 TechNet 中 (用 "VFPCOM" 关键词查询)。 

要获得更多的关于 Office 应用的对象模型、包含的事件和被传递给它们的参数的信息,查看 MSDN。 

下载 10COATSC.ZIP
题外话: inspector 配件是什么? 
像大多数对象模型一样,Outlook 对象模型有一个清楚的层次。在(对象模型)树的顶端是 Application 对象。直接在它下面的是 Namespace 对象。Namespace 对象代表理论上的 Outlook 数据储存的根。文件夹(例如收件箱、日历、发送数据项和任何用户自定义文件夹)属于 namespace 对象或其它高层文件夹。 

最后,文件夹包含数据项(items)。数据项是邮件信件、约会、任务、便签等等在文件夹中的东西。在文档的列表中总共有 16 种类型的数据项。Outlook 需要一个显示数据项的方法。为了做到它,要使用一个 inspector 对象。MSDN 简单的把 inspector 对象定义为:“当一个 Outlook 数据项被显示的时候所用的窗口”。inspector 对象是一个数据项的用户界面。inspector 对象允许访问工具栏,如果数据项已被定制的话可以对任何页、如果 Word 被使用为一个 Email 编辑器的话可以对 wordmail 编辑器的对象模型操作。 

例如,要显示在收件箱文件加重的第一个数据项,你可以使用下面的代码: 

#DEFINE olFolderInbox 6 
* 进到进入对象的层次来获得数据项loOutlook = createobject('outlook.application') 
loNameSpace = loOutlook.GetNamespace("MAPI") 
loInbox = loNameSpace.GetDefaultFolder(olFolderInbox) 
loItem = loInbox.Items(1) 
* 获得数据项的默认inspector 
loInspector = loItem.GetInspector() 
* 显示数据项 
loInspector.Display() 

通过改变传递给 GetDefaultFolder() 的参数来试验一下。例如,给它传递 olFolderCalendar(9) 将显示在用户的默认日历文件夹中的第一个数据项。你还可以使用文件夹的集合索引来返回一个非默认的文件夹。如果在层次的顶部有一个名为 "My User Defined Folder" 的文件夹,那么下面的代码将返回一个那个文件夹的变量: 

loNameSpace.Folders("My User Defined Folder") 

要获得更多的关于 Outlook 对象模型的细节信息、包含图表和示例代码,请查看 MSDN 文档。


标签:

本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@evget.com


为你推荐

  • 推荐视频
  • 推荐活动
  • 推荐产品
  • 推荐文章
  • 慧都慧问
扫码咨询


添加微信 立即咨询

电话咨询

客服热线
023-68661681

TOP