0

好吧,这有点棘手……

我正在使用 VS 2010 和 VSTO 以及 VB.NET 为 MS Outlook 2007 编写插件。我的目标是提示用户打印他们从某些电子邮件地址收到的电子邮件。(这将通过一个简单的 MsgBox 完成。)

具体来说,我希望在用户阅读完电子邮件后得到提示。我的概念是它应该与 Outlook 中的“阅读回执”功能类似。(你知道,那些烦人的事情...... “发件人已要求您提供已阅读此电子邮件的收据等等”

因此,用户阅读电子邮件,然后当他们关闭检查器(或者如果他们在资源管理器视图中将焦点更改为不同的项目)时,MsgBox 会弹出。我注意到当电子邮件变为“已读”时,时间匹配。

几天来,我一直在谷歌和 MSDN 和教程网站上追逐这个,这就是我发现的:

第 1 轮: Mailitem 对象有一个 UnRead 属性,它也有一个 PropertyChange 事件。我可以在收件箱中的每个 Mailitem 上使用 AddHandler for PropertyChange,将它们绑定到一个子例程中,该例程检查 PropertyChange 事件的参数以确保它是未读的。似乎相当可行,除了 PropertyChange 没有传递调用对象的身份,所以我无法知道收件箱中的哪些电子邮件刚刚丢失了“未读”状态。

事实上,似乎没有一个 Mailitem 事件传递它们的身份,可能是因为有人(我猜是 MS)假设您首先拥有指向 Mailitem 对象的直接指针。所以这条路线似乎行不通。

第 2 轮: 我可以将收件箱中的所有邮件项收集到一个集合中,然后将它们限制为仅未读的邮件项。

Dim inbox As Outlook.MAPIFolder = Nothing
Dim WithEvents unreadItems As Outlook.Items

inbox = Me.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox)
unreadItems = inbox.Items.Restrict("[Unread]=true")

由于 unreadItems 是用事件变暗的,我可以编写一个 Sub 来处理 unreadItems.ItemRemove,这样可以正常工作。但是 ItemRemove 事件没有对象参数!嗬!

第 3 轮: 假设我做相反的事情:我获取收件箱内容并限制为 [Unread]=false,然后使用 .ItemAdd 事件。这在一定程度上会起作用,除了理论上它会在用户将“[未读] = false”项目从任何文件夹转储到收件箱时调用,而不仅仅是从收件箱中的未读组更改为已读组。所以,除非我在这里误解了一些东西,否则也不是一个选择。

第 4 轮: 现在,我还想到了简单地将 Inbox 项目集合 WithEvents 调暗并关闭 .ItemChange 事件,但该事件并没有真正指定对象发生了什么变化,所以没有骰子。


最后,我对此感到非常困惑。我非常接近放弃我的目标。一个蹩脚的替代方法是在用户收到来自指定地址之一的电子邮件时提醒用户(因为我相信 Application.NewMail 事件不会给我带来任何麻烦)。但是,我将不得不简单地提醒用户——我不会提示他们打印他们甚至还没有阅读的电子邮件。

这种选择是不可取的,我想我会提出我的问题以供检查和建议。

-马特

PS我来自使用Objective-C制作iPad应用程序,我自己构建大部分对象层次结构......不得不处理具有这些限制的COM对象很奇怪。

4

1 回答 1

3

I'm not quite sure how you want your UI to behave, because it's not quite clear when the user is done reading their email. One way to look at it is that they are done when they have looked at it, meaning that the inspector window has shown the mail and the user is switching to another one. To catch that, you would probably be best off watching events from the inspector, not the mail items. The other way to look at it is that a mail is read whenever it is marked as Read. Be aware that the user may actually turn off the option to mark items as read automatically! This can be done in Tools->Options->Other->Reading pane, like this:

enter image description here

Also, the user may select items and mark them as read manually, so you need to think about what you want do in that case.

If you want to watch for the change in "read" property of the MailItem, you are very close in round 1. The thing you need to add is that you shouldn't tie all of your handlers to a single subroutine in a single object instance. Instead, you can create your own class, something like this (C# code):

class ItemWatcher
{
    // The Outlook mailitem to watch for
    private Microsoft.Office.Interop.Outlook.MailItem itemBeingWatched = null;

    public ItemWatcher(Microsoft.Office.Interop.Outlook.MailItem item, Form1 parentForm)
    {
        itemBeingWatched = item;
        itemBeingWatched.PropertyChange += new Microsoft.Office.Interop.Outlook.ItemEvents_10_PropertyChangeEventHandler(itemBeingWatched_PropertyChange);
    }

    void itemBeingWatched_PropertyChange(string Name)
    {
        // Respond to property <Name> in the object itemBeingWatched having changed
    }
}

Then you need to create a collection of your ItemWatcher classes and set them to watch your emails.
Note that you will also need to watch for items you need to add/remove from your collection of watched items, when a new mail arrives or an old mail is deleted/moved.

于 2011-11-16T14:49:46.957 回答