Okay, this is a bit of a tricky one...
I am programming an add-in for MS Outlook 2007, using VS 2010 and VSTO, and VB.NET. My goal is to prompt the user to print off emails that they receive from certain email addresses. (This would be done with a simple MsgBox.)
Specifically, I would like the prompt the user when they are done reading the email. My concept is that it should work similarly to the "Read Receipt" functionality in Outlook. (You know, those annoying things..."The sender has requested a receipt that you have read this email blah blah")
So, the user reads the email, and then when they go to close the Inspector (or change focus to a different item if they are in Explorer view) the MsgBox pops up. I have noticed that the timing on this matches when the email becomes "read".
I have been chasing this across Google and MSDN and tutorial websites for a few days, here's what I've found:
Round 1:
The Mailitem object has an UnRead property, and it also has a PropertyChange event. I can use AddHandler for PropertyChange on every Mailitem in the Inbox, tying them into a single Subroutine that checks the argument of the PropertyChange event to make sure it's UnRead. Seems fairly workable, except that PropertyChange doesn't pass the calling object's identity, so I have no way of knowing what email in the Inbox just lost "unread" status.
In fact, none of the Mailitem events seem to pass their identity, probably because someone (MS I guess) assumes that you have a direct pointer to the Mailitem object in the first place. So this route doesn't seem to work.
Round 2:
I can grab all of the Mailitems in the Inbox into a collection, then restrict them to just the Unread ones.
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")
Since unreadItems was Dimmed WithEvents, I could write a Sub to Handle unreadItems.ItemRemove, which would work fine. But the ItemRemove event has no object argument! Doh!
Round 3:
Let's say I do the opposite: I get the inbox contents and restrict to [Unread]=false, then use the .ItemAdd event. This would work to a degree, except that it would theoretically call whenever an "[Unread]=false" item was dumped into the Inbox by the user from any folder, not just a change from the Unread to Read group within the Inbox. So, unless I'm misunderstanding something here, also not an option.
Round 4:
Now, something I also thought of was simply Dimming the Inbox items collection WithEvents and going off the .ItemChange event, but this event doesn't really specify what changed about the object, so no dice.
In closing, I'm pretty darn stumped with this. I am very close to backing down from my goal. A lame alternative is to alert the user when they receive an email from one of the designated addresses (because I believe the Application.NewMail event won't give me any hassle). But then, I will have to simply alert the user--I won't prompt them to print an email they haven't even read yet.
This alternative is undesirable and I figured that I would present my problem for inspection and suggestion.
-Matt
P.S. I'm coming from making iPad apps with Objective-C, where I'm building most of the object hierarchy myself...it's weird to have to deal with COM objects that have such limitations.
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:
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.
Related
I'm developing an Outlook AddIn using the NetOffice library, but I guess the problem is similar for VSTO.
I want to handle following events in Outlook regarding appointments:
The user drag'n'drops appointments to change the date of the appoinment
The user double clicks the appointment subject and edits it directly on the calendar
The user gets an ICS file by email which updates some data on the appointment
So that's pretty easy:
var exp = App.Session.GetDefaultFolder(OlDefaultFolders.olFolderCalendar);
(exp.Items as Items).ItemChangeEvent += Addin_ItemChangeEvent;
So now on each case I need, my event handler fires up. However the problem is, that I need to recognize, if the change on the appointment is because of user action on the calendar or an ICS file received.
I really stuck on that one, any tips?
You can use marks for that. I try to explain my solution. In each outlook item (it can be AppointmentItem and MailItem) you have a property UserProperties, you can create mark variable like a string public const string ICSMark = "ICSMark"and add new user property with this mark appointmentItem.UserProperties.Add(ICSMark, OlUserPropertyType.olText);. When you event is occurs you can check your item for this mark UserProperty mark = appointmentItem.UserProperties.Find(ICSMark);, if mark is not null, it was updated from ICS file.
I want to get the list of all events for any particular component dynamically. For example : If I take a Textfield , how can I get all possible events that are mentioned in ExtJs API Doc. so that user can choose and assign the event for any component.
component.events
Contains the list you need. You could have found out by yourself reading the source of addEvents method, which is linked from any event you wanted to find in a list.
For those still wanting an answer to this, https://coderwall.com/p/jnqupq/easily-capture-all-events-on-a-component-in-extjs has provided a nice means of doing so.
When debugging an ExtJS application, you'll often find it useful to listen to all events fired by a specific component. There is actually a handy built-in static method to do this called Ext.util.Observable.capture().
Here's a handy snippet that simply logs the event name and all arguments:
Ext.util.Observable.capture(myObj, function(evname) {console.log(evname, arguments);})
Even better, if you're currently inspecting your component's main element in your browser's developer tools, you can do this:
Ext.util.Observable.capture(Ext.getCmp($0.id), function(evname) {console.log(evname, arguments);})
Where $0 is the currently selected element. Should work fine in Chrome, Firefox, Opera, Safari.
If you don't want those logs to pollute your console anymore, simply call releaseCapture on your object:
Ext.util.Observable.releaseCapture(myObj);
This removes all captures on a given object so you don't have to reference your listener explicitly (which was likely an anonymous function :)).
Bonus tip: also be sure to check out the observe method which does something similar but allows you to listen to all events fired by all instances of a given class.
In a VB6 project, I would like to be notified when an edit control (text field) has been updated (i.e. : character string has been added by a user into the text field).
I did not find any documentation on the different events which can be catched for an edit MFC control.
Thanks in advance.
Its the _Change event. However, I personally do not like this event since it is notoriously unreliable.
Private Sub txtYourTextFieldControl_Change()
' some code here
End Sub
* edit *
We are talking about VB6 textbox, correct? I am not sure what MFC has to do with this.
I recently started another thread without an account, so I'm reposting the question here with an account so I can edit current links to the program so other users can follow this. I have also updated the code below. Here is my original question:
I read the other post here on Outlineviews and DND, but I can't get my program to work. At the bottom of this post is a link to a zip of my project. Its very basic with only an outlineview and button. I want it to receive text files being dropped on it, but something is wrong with my code or connections. I tried following Apple's example code of their NSOutline Drag and Drop, but I'm missing something. 1 difference is my program is a document based program and their example isn't. I set the File's Owner to receive delegate actions, since that's where my code to handle drag and drop is, as well as a button action. Its probably a simple mistake, so could someone please look at it and tell me what I'm doing wrong? Here is a link to the file: http://dl.dropbox.com/u/7195844/OutlineDragDrop1.zip
You're not responding to NSOutlineView's drag-validation message.
Your original code implemented tableView:validateDrop:proposedRow:proposedChildIndex:. As I pointed out on that question, that's wrong when your table view is an outline view; NSOutlineView will not send a table-view drag-validation message, only an outline-view drag validation message.
You've since changed your drag-validation method to be declared like so:
- (NSDragOperation)outlineView:(NSOutlineView*)view
validateDrop:(id <NSDraggingInfo>)info
proposedRow:(int)row
proposedChildIndex:(NSInteger)index
But nothing actually sends such a message.
Remember that NSOutlineView rarely deals with row indexes, since those can change as parent rows are expanded and collapsed. It deals instead with “items”, which are generally model objects.
Therefore, the correct validation method is:
- (NSDragOperation)outlineView:(NSOutlineView*)view
validateDrop:(id <NSDraggingInfo>)info
proposedItem:(id)item
proposedChildIndex:(NSInteger)index
Notice the name of the third component of the selector, and the type and name of the argument that goes with it.
With this change applied, your data source validates drops.
I am trying to disable a field, i.e. grey it out and not allow the user to select it. To achieve this effect I am currently calling
crmForm.all.new_attribute1.disabled = true;
crmForm.all.new_attribute2.Disabled = true;
The Disable, with a capital D, makes the field grayed out but the user can still put the cursor in that field or tab to it.
The disable, with a little d, makes the field unavailable to the cursor and via tab, but gives no visual indication that it can't be interacted with.
Is there a better way to do this, one call that will achieve similar results or am I stuck having both there?
Using "Disabled" property should work.
You can try putting this code in OnLoad event of Account entity (don't forget to enable Event and Publich entity!):
crmForm.all.accountnumber.Disabled = true;
And "Account Number" will be blocked and greyed as seen in this picture:
(source: vidmar.net)
You are talking about readOnly and disabled.
A great article was posted http://customerfx.com/pages/crmdeveloper/2006/03/06/readonly-and-disabled-fields.aspx ... maybe this could help.