Tom,
Thanks for the examples. I'm still hung up on the document template
issue. I did stumble across a really nice article that explains the
issue in some detail:
http://dave.thielen.com/articles/Word%20Add-In%20Part%201.htm
When you create menu objects, you’ll need to keep a couple of things
in mind. First, you must store the returned menu objects in a location
that will exist for the life of the program. The menus are COM objects
and if no persistent C# object is holding them, they are designated for
garbage collection and your events will stop working the next time the
garbage collector runs.
Second the call
CommandBarPopup.Controls.Add(MsoControlType.msoControlButton,
Type.Missing, Type.Missing, Type.Missing, false) must have false for the
final parameter. If this is set to true, as soon as any other add-in
sets Application.CustomizationContext to another value, all your menus
go away.
Apparently temporary (the 5th parameter) isn’t the life of the
application, but the life of the present CustomizationContext set as the
CustomizationContext. If another add-in changes the
CustomizationContext, your menu disappears. Given a user can normally
have several add-ins, you can never set the 5th parameter to true. The
downside is you’re adding your menus to the default template (Normal if
you don’t change it) permanently. I don’t think you can have menus exist
for the life of the application, but not have them added to the template.
Give Users a Template
Another approach is to give users a template to use with your add-in.
The template doesn’t have to do anything, but on startup, you look for
that template and add your menus only if the template exists. You also
add your menus to your template. In essence, you’re using the existence
of the template as an Attribute. This is a clean way to have your add-in
appear only when you want it to and have it not touch any other part of
Word.
Each time your program starts, you need to determine if your menu has
already been added (CommandBarControl.Tag is useful for this). If it
isn’t there, add it. If it is there, either delete it and then add it or
set your events on the existing items. I delete and add it because over
the course of writing the program, the menu items change at times. If
you delete and add it, save the location of the menu and add it there.
If a user customizes her menu by moving the location of your menu, you
don’t want to force it back to the original position the next time Word
runs.
When you set the menus, this changes the template and Word normally asks
the user when she exits if she wants to save the changed template. To
avoid this, get the value of the default Template.Saved before making
the changes and set Template.Saved to that value after you’re done. If
the template was not dirty when you first got the value, it will be set
back to the clean value upon completion:
// the template to use
private Template TemplateOn
{
get
{
// find the WordObject template - if not use AttachedTemplate
because that's better than nothing.
Templates tpltColl = ThisApplication.Templates;
foreach (Template tpltOn in tpltColl)
if (tpltOn.Name == "MY_TEMPLATE.DOT")
return tpltOn;
return ThisApplication.NormalTemplate;
}
}
...
// find the WordObject template - if not use AttachedTemplate because
that's better than nothing.
Template thisTemplate = TemplateOn;
// set the customization to our template and see if the template is dirty
bool clean = thisTemplate.Saved;
ThisApplication.CustomizationContext = thisTemplate;
...
thisTemplate.Saved = clean;
One warning: Don’t look at the Template.Dirty value using the debugger.
The act of looking at it sets it to dirty. This is a true Heisenbug.
(The Heisenberg theory is that the act of observing a particle affects
the particle.)
And even after you take all these measures, there is one more issue.
Sometimes when you close all documents so you have Word running but no
document open, the menu events still fire fine but calls to
CommandBarControl.Enabled throw exceptions. Once you create a new
document, the problem usually goes away—unless you have two instances of
Word, close the first one, then bring up a document in the second one.
Then the problem remains. The solution to this is covered in Part II.
Post by Tom WinterOK, I've got some stuff that might help you out. If you go to my web site
http://www.amosfivesix.com/downloads/
There are a couple of sample projects that you can download. I would
recommend the Word 97 COM Add-in Sample Project. Now this sample does more
than what you are asking, so it might be confusing. Sorry I don't have a
more streamlined sample that does just what you are looking for. The Word 97
sample also links up the command buttons using "old fashioned" macros,
rather than event sinking that was introduced in Word 2000.
* Create an empty TEMPLATE to hold your menu customizations. You'll then
need to write some code to create the menu items in this template. Make sure
the CustomizationContext is set to your template. Make sure the menu items
all have their TAG property set uniquely. This is how you'll find them
later. Remember, this code to create the menu items is only going to be
needed at DESIGN time. You run the code once to create the menu items in the
template file. Then save the template file.
* Install your COM Add-in as appropriate. Install the template file in the
same folder as your COM Add-In. You don't need to worry about finding Word's
STARTUP folder or any goofiness like that.
* In your COM Add-In, during OnConnection or OnStartupComplete, use
oWordApplication.AddIn.Add VB.App.Path & "NameOfTemplate.dot" , True
This will load the add-in as a global template. The menu items should now
show up in the user interface. Remember, there is no code in your add-in to
create the menu items. Simply loading the template gives you your menu
items! Don't forget to do
oWordApplication.AddIns("NameOfTemplate.dot").Delete to remove the add-in
during OnDisconnection. or OnBeginShutdown().
* Now you need to sink up to your menu items. Do something like
Set oMyButton =
oWordApplication.CommandBars.FindControl(Tag:="UniqueTagIGaveToEachButton")
That's about it. Since your buttons are ONLY in your custom template, you
don't have to worry about them hanging around after you uninstall the
template. And since your COM Add-In loads the template manually, you don't
have to worry about Word's STARTUP folder. This works great for static
menus. If the menu needs to change at run time (add or remove an item based
on something), it may get more complicated, but this basic scenario should
work for you.
If you need more details let me know. I may work the whole thing up into a
sample project.
--
---------------------------------
Trevor Lowing
Satellite Beach, Fl
tlowing@-removenospam-lowing.org
---------------------------------
Need help with:
Access?
http://www.mvps.org/access/
Outlook?
http://www.slipstick.com/
Visio?
http://www.mvps.org/visio/
HTML/CSS?
http://www.NCDesign.org
Scripting(VBScript/JScript/WSH/XML)?
http://www.DevGuru.com
http://cwashington.netreach.net/
http://developer.irt.org/script/script.htm
---------------------------------