AddHandler to a button on a new inspectors commandbar

  • Thread starter Thread starter Steffen Grellmann
  • Start date Start date
S

Steffen Grellmann

Hi newsgroup,

I'm trying to add a custom button to a new inspectors commandbar in
Outlook 2003. Word is used as e-mail editor. Everything is working
fine so far.

But what would be the correct technique to add a handler to my custom
button? If I add the handler like shown in the code below, with every
new inspector that is opened a new handler is added to my button. This
lets the click procedure fire that many times inspectors has been
opened so far. Would it be a solution to initialize a Boolean variable
to check if the handler has been added or which is the preferred way
to add the button handler in this constellation?

Any help is highly appreciated.

Kind regards,

Steffen

Public Class ThisAddIn

Dim MyButton As Office.CommandBarButton
Dim selectInspectors As Outlook.Inspectors

Private Sub ThisAddIn_Startup(ByVal sender As Object, ByVal e As
System.EventArgs) Handles Me.Startup

selectInspectors = Application.Inspectors()
AddHandler selectInspectors.NewInspector, AddressOf
NewInspector_Event

End Sub

Private Sub NewInspector_Event(ByVal new_Inspector As
Outlook.Inspector)

If
new_Inspector.CurrentItem.MessageClass.ToUpper.Contains("IPM.NOTE")
Then
Try 'inserting Button
MyButton = new_Inspector.CommandBars.FindControl(, ,
"MyTag")

If MyButton Is Nothing Then 'only if doesn't exist
MyButton =
new_Inspector.CommandBars.Item("E-mail").Controls.Add(1, , , , False)

With MyButton
.Style =
Office.MsoButtonStyle.msoButtonIconAndCaption
.Caption = "MyCaption"
.Tag = "MyTag"
.TooltipText = "MyTooltipp"
.FaceId = 1100
End With

AddHandler MyButton.Click, AddressOf ButtonClick
Else
AddHandler MyButton.Click, AddressOf ButtonClick
End If

Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End If
End Sub

Private Sub ButtonClick(ByVal ctrl As Office.CommandBarButton,
ByRef Cancel As Boolean)
MessageBox.Show("You clicked: " + ctrl.Caption)
End Sub
End Class
 
Usually to handle multiple open Inspectors we use wrapper classes in a
collection to hold the references open so they don't get garbage collected.
The wrapper class has declarations for Inspector and the item shown in the
Inspector. The UI is usually added on the first Inspector.Activate() event.

The reason for adding the Inspector in Activate() is that in NewInspector()
you get a weak object reference in Outlook 2007 that doesn't have all
properties of the item instantiated.

For avoiding multiple clicks you make sure to create a unique Tag property
for each button you create. That way the click only fires in the specific
Inspector where the button was clicked.
 
Hi Ken,

thank you for replying. I'm working with an Inspector wrapper class
now. Nevertheless with this technique the handler

AddHandler oInspClass.myMail.Close, AddressOf myMail_Close

is already fired once independently from the number of Inspectors has
been opened so far.

But this technique is not working for the button click - I'm still
receiving multiple clicks when the handler is defined like this:

AddHandler oInspClass.MyButton.Click, AddressOf ButtonClick

BTW, it's a Button on the "E-Mail"-commandbar which is IMO part of the
Wordmail editor. The button is added Temporary = TRUE, but is
persisting in Word afterwards.

Do you have an example that demonstrates the adding of a handler for a
button on a Wordeditor commandbar considerating multiple Insepctors?

Kind regards,

Steffen
 
Are you creating a unique Tag property for each button you create? That's a
requirement for the button not to fire multiple times when it's clicked.

WordMail has its own set of rules. For one thing any changes you make using
Temporary := True are not respected. You have to explicitly delete your UI
(a good practice even without WordMail). When you add UI to Word you are
modifying the CustomizationContext, which usually is normal.dot but can be
set to other locations. If CustomizationContext.Saved == False then either
Word will save the changes to the context location or prompt on exit to
save. So after each change to any UI element you have to force
CustomizationContext.Saved to True to prevent that. That's after you delete
the UI elements.

The Tag behavior isn't only with WordMail, it follows with any UI elements
you add: a unique Tag per element.
 
Hi Ken,

in the meantime I've taken a closer look at the Inspector Wrapper
example from your website and adapted it for using in VSTO 2005 in
conjunction with OL 2003. So I've got rid of the multiple clicks. As
you may remember I'm trying to add a button to a WordMail commandbar.
This is working fine so far with one exception: If multiple drafts of
a new mail are opened, the button is added multiple times.

I thought I could fix this behaviour with a closer look at the
CreateButtons and CreateMenus procedures in your Inspector Wrapper
code, but I'm a bit confused about setting m_obj = Nothing if WordMail
is true. What has been your initial idea when checking for WordMail?

Beside that, I'm not clear about the UnInitHandler in objInsp_Close
because I can't find an UnInitHandler Sub or Function in your code.
What should this UnInitHandler do?

Kind regards,

Steffen
 
In general with WordMail you always end up with multiple
toolbars/buttons/etc. when multiple WordMail items are opened at once.
There's really no way to avoid that with WordMail 2003 or earlier. So you
have to work around that.

First, if you always add your Inspector wrapper Key value to any tags you
create that enables the code to find the specific UI created for that
Inspector among multiple open items. The custom UI you created was added to
Word as part of any CustomizationContext and will remain in the template
used for CustomizationContext unless explicitly deleted, since Word doesn't
honor the Temporary argument used when creating UI.

In addition you have the problem of being prompted when Word closes that
something changed in Normal.dot if the user has Word set to prompt for that
on closing.

I always set up a Word event handler in each Inspector wrapper. I
instantiate that from Inspector.WordEditor, which is the Word.Document
object. From there I can get WordEditor.Parent, the Word application object.

That lets me use wordApp.CustomizationContext.Saved = True every time I make
any changes to any Word UI (add, delete, change visibility, change enabled
state, etc.). That prevents the prompt to save.

That also lets me handle the Word.WindowActivate() event. When that fires
when a WordMail item gets activation I check for wn.EnvelopeVisible. If True
that means the window is a WordMail window, if False it's not. If it's not a
WordMail window (user opened a document from the file system or a new
document) I set the visibility of any UI I created to False so the user
doesn't see it in that document.

If it is a WordMail window I iterate the CommandBars collection of the
document and find all instances of my UI. If the tag in the UI object ends
with the Key value for that Inspector I enable and make visible that UI. If
it's from some other WordMail document (a different Key value) I make that
UI element invisible and disabled so the user doesn't see it even in the
View, Toolbars menu.

Then when the item is closing I get the UI I created and delete it so it
doesn't persist.
 
Hi Ken,

thank you very much for that deep insight. I guess I can work on with
that additional informations. I really appreciated your time and help.
Kind regards,

Steffen
 
Back
Top