2005.07.13 04:05 PM
Temporary Word CommandBars
After years of watching various Word add-ins leave behind temporary menus and/or toolbars (or the items that appear on them) after the add-ins have been unloaded, I've concluded that many Word add-in developers don't know that the Temporary parameter of the Add method of the CommandBars and CommandBarControls collections doesn't apply to Word.
Here's what Microsoft says about the Temporary parameter:
The Temporary feature is intended for other applications that do not support session-specific settings. Because Word can store information in global templates or local templates, you can get all of the Temporary functionality without using the Temporary flag.
Well, that's true, you can. Unfortunately, I don't think a lot of Word add-in developers knew they had to. Or, having figured it out, knew how to.
I would like to help.
If you're going to add CommandBar or CommandBarControl objects to Word at run-time, and you want them to be truly temporary, set the Application.CustomizationContext to something other than Normal.dot before you begin making your changes. Ideally, you should set it to target your own add-in (i.e., ThisDocument), make your mods, and then set the add-in's Saved property to True to avoid being asked to save your changes when Word (or your add-in) closes. You should also be a good neighbor and set the Application.CustomizationContext back when you're done making your changes. But, don't just set it to Application.NormalTemplate. Instead, save a reference to whatever was in it before you pointed it at your add-in and then set it back to that when you're done.
Here's an example:
Public Sub AutoExec() ' Document_Open, Document_New, AutoOpen, AutoNew, etc. Dim OldContext As Object ' Preserve and switch the customization context. Set OldContext = Application.CustomizationContext Application.CustomizationContext = ThisDocument ' Add a CommandBar and CommandBarButton. Dim NewCommandBar As CommandBar Dim NewCommandBarButton As CommandBarButton Set NewCommandBar = Application.CommandBars.Add("My Toolbar", msoBarFloating) Set NewCommandBarButton = NewCommandBar.Controls.Add(msoControlButton) With NewCommandBarButton .Caption = "Press Me" .Style = msoButtonCaption .OnAction = "PressMe" .Enabled = True .Visible = True End With NewCommandBar.Enabled = True NewCommandBar.Visible = True ' Switch the context back and mark this template as having been saved. Application.CustomizationContext = OldContext ThisDocument.Saved = True End Sub
Another interesting tidbit that I didn't know about (like the things you wrote about Word's handling of sections and section breaks, a few months ago).
Thanks, and keep the posts coming!
Helen | 2005.07.14 03:23 AM
Thanks, Helen. I'll try!
ewbi.develops | 2005.07.14 07:31 AM
This works great, as long as your addin is not also for Outlook. Outlook will launch an instance of MS Word that does not open a document. Because of this your code will produce an error.
mervin13 | 2005.10.21 09:06 AM
Thanks for the information. I haven't had a chance to look at this, but if I get time I'll take a closer look.
ewbi.develops | 2005.11.08 03:53 PM
Thanks, this is a good lead and might help me resolve a problem I've been beating on for days.
Note: when adding the new command bar, do not set Temporary:=True or the menu will disappear when the CustomizationContext changes.
Still having a problem: I'm trying to add a menu using
The menu appears and remains until changing CustomizationContext back to its original setting (thanks for the tip), then DISAPPEARS!
Any comments? Or just more Microsoft Weird...
Scott | 2006.05.05 01:50 PM
Yes, it qualifies as "Microsoft Weird". This is odd behavior that occurs when a document switches the CustomizationContext to itself, modifies the CommandBars in some way, and then switches the context back to whatever it was. The changes made during the switch don't appear (actually they do, but only very quickly, then they disappear). However, if you then open a new document and immediately close it, or just switch back to the original context-switching CommandBar-modifying document, the changes will appear. I've noticed this in Word 2003, but wouldn't be surprised if it occurred in all versions. This is not the case with templates loaded as global add-ins.
If your document or template isn't being loaded as a global add-in one thing you can do is add the following logic to your code, just after you've made your CommandBar mods and switched the CustomizationContext back:
Dim d As Document
Set d = Documents.Add(, , , False)
This causes Word to get its act together and recognize the CommandBar mods in effect for the current document.
ewbi.develops | 2006.05.09 03:37 PM
The example above works well, but not when Outlook is using Word as the e-mail editor. If you happen to start a Word session via Outlook, the custom menu does not show up, or it does, but with the wrong menu items. I've spent quite a few hours searching the net for a sample add-in that would achieve this:
1. Loads a custom menu containing macro commands, from a .dot file in the Word startup folder. (The .dot file adds the menu via AutoExec.)
2. Should not modify the normal.dot, but only itself, with CustomizationContext.
3. Works either with Word started normally or via an Outlook session.
For some reason, it seems like I have to choose between item 2 or 3 - can't have both working. If you have tips or links to fix this, I'd greatly appreciate. I can send you my .dot add-in if you want to look at the code. Since I am not a programmer, may be just a simple tweak is required...
Thanks in advance
Erik B | 2006.05.16 05:31 AM
Hi Erik B,
Yeah, the whole use-Word-for-email thing really complicates the add-in story. Here's what I know about it.
The instance of Word that is started by Outlook when using Word as the email editor loads the global Word add-ins but does not execute their autoexec routines. Subsequently "starting" Word by clicking the Word shortcut or by opening a Word document, if done *after* Outlook starts its instance, will unfortunately use the same instance of Word that was started by Outlook, which means you'll be running in an instance of Word in which none of the loaded global add-ins will have had their autoexec routines run.
On the flip side, if you start an instance of Word *before* starting Outlook, allowing the global add-ins to load and execute their autoexec routines as expected, and if you leave this instance of Word running while Outlook is started, Outlook will use this instance to create new Word document instances when editing emails. Any commandbars added to the CustomizationContext of any of the global add-ins (as described in my post) will be available, but generally invisible in Outlook's Word email editor - you can make them visible by right-clicking the toolbar and selecting them.
What's really unfortunate is that sometimes after closing Word and Outlook, an invisible orphan instance of Word is left running in the background. When this happens, any subsequent "starting" of Word, whether directly or via Outlook, will use this invisible instance, whose add-in initialization characteristics will be determined by whether it was started before or after Outlook was started.
Btw, in the first scenario I described, if after starting Outlook you use the Outlook Word email editor's File | New menu to "start" a new Word document, or just click the Word shortcut to "start" it directly, you can manually run the autoexec routines of any loaded global add-ins by pressing Alt-F8 and selecting the appropriate routine from the list (you may have to filter the list using the dropdown to find the right ones to run). Once you do this, any Word environment changes made by the now initialized global add-ins will be present and available in any Outlook Word email editors as well.
I'm not sure how different all this behavior is when using Word COM add-ins as opposed to DOT add-ins. It's possible they're loaded and initialized with the Outlook-spawned Word instance. Perhaps only if they're digitally signed and trusted? Not sure.
Hope this helped. Good luck.
ewbi.develops | 2006.05.18 04:45 PM
Hi all, I have tried this from a global vba macro addin and it does indeed work, but I frequently get corrupted normal.dot after using it for a while. has anyone else had this issue? I am using Application.CustomizationContext = ThisDocument
Jason | 2006.07.27 02:59 PM
I haven't seen this type of code in a global add-in template corrupt a Normal.dot before. Have you verified that the global add-in template is responsible for the corruption (i.e., run without for a sufficient time, no corruptions, run with the add-in for some time, get corruptions)? If so, then I'm wonderng what else might be happening in the global add-in template - any other manipulation of commandbars, styles, etc. that might be impacting Normal.dot?
ewbi.develops | 2006.07.27 03:10 PM
I seem to be having a similar problem to Scott in that I have created a custom commandbar, but can't get it to stay put!
Any ideas or suggestions will be very welcome!
Thanks in advance.
I've tried adding the code that you posted to force Word to get its act together to no avail :-(
My commandbar exists, I can 'right-click' on an existing toolbar and select my commandbar to make it visible. I just can't get the thing to stay visible on its own!
Dan | 2007.01.08 09:23 AM
Rather than try and diagnose the issue here in a dozen back and forth comments, can you just send me a small document that illustrates the problem, preferably the one that includes the code I described above for Scott (that apparently isn't working for you)? You can send it to email@example.com. Be sure to include an indication of the version of Word you're having trouble with. Thanks.
ewbi.develops | 2007.01.08 10:01 AM
If you find a solution, please write back to this forum with the answer so others can benefit from it.
Mike Johnson | 2007.01.10 02:48 AM
Yep, that's what we do. However, I haven't yet heard from Dan. If you've got a similar issue and a document that'll reproduce it, please feel free to forward me a copy.
ewbi.develops | 2007.01.10 07:00 AM
I have the same problem with a ODMA-like program I wrote.
Is there any solution you guys came up?
I'm really desperate!
Roberto | 2007.01.12 02:03 AM
Looks like you aren't alone. What I'm desperate for, though, is a sample document-based commandbar-building macro that is consistently failing to show itself on load so I can investigate what's going on (beyond what's suggested in my post and in the comments above). If you've got a sample you can share, please send it along to firstname.lastname@example.org.
ewbi.develops | 2007.01.12 02:11 AM
hi, ewbi developer, sorry but that's not my case. Unluckily (or luckily?!?) my .dot based addin works fine, except for the myapp_Event() catching part.
Is there anything I can do aside from starting Word before outlook to make it right? Like forcing Word to open my addin even if I start a Word instance from Outlook?
roberto | 2007.01.18 07:46 AM
I forgot there were two threads running here: one involving non-visible Commandbar changes following CustomizationContext changes, and one involving Outlook's no-add-in loading of a Word instance. I asumed you were having an issue with the former, but it seems it's the latter.
Unfortunately, beyond what I wrote about this in an earlier comment above, I don't have much to add. I'm not sure there is a way to force Word to load your add-in when it is started by Outlook. Perhaps a registered COM add-in would act differently? I just don't know. If you find a solution, though, please come back and share it with us.
ewbi.develops | 2007.01.18 10:09 AM
I tried to write an Add-in to see if the theory about them (the acting differently thing...) was correct, and it worked! Even if I start Outlook before Word, now in my OnStartupComplete() function in my c++ addin I force the AutoExec function to run anyway and all the events are intercepted seamlessly.
I got crazy figuring out how to use the Application::Run() and then Application::RunOld() function worked, but now all is fine and I can run from the C++ addin the VBA macros.
In the beginning I wrote an event driven c++/ATL addin, then I figured out that if I was able to call vba macros, I could setup the vba event object (the one that didn't start launchung Outlook) and use it to intercept all the events without the c++ part.
roberto | 2007.02.04 01:21 PM
Roberto, thanks for the update (yeah, I know, I'm way behind). I'm not a C++ or ATL kind of guy, but hopefully someone will find what you've done helpful. Thanks again for coming back to share it.
ewbi.develops | 2007.04.26 01:06 PM
I have tried all the suggestions in this article but my toolbar still gets hidden when I change Context. I'm not using VBA but instead a COM object built using VB.
If I cahgne my CustomizationContext to a new .dot file all goes well. I can breifly see my toolbar but then at some later point the CustomizationContext i changed and it is hidden. I do not add the toolbar as a temporary bar but this doesn't seem to matter.
I am able to see my bar by rightclicking and checking the checkbox to show it. I don't want to have to do this each time however.
Anybody got any ideas?
Tim | 2007.05.09 05:15 AM
What you're describing sounds just like the "Microsoft Weird" behavior described above in a comment from Scott. Did you see my response to Scott, and have you tried the workaround?
ewbi.develops | 2007.05.09 08:18 AM
Yes thanks - I found that particular problem. I had PDF Creator installed and it seems to hide my toolbar. I've still not cracked the problem but I'm getting close. I'll post what I find if I manage to do it.
Tim | 2007.05.10 04:09 PM
Miloš | 2008.10.09 06:20 AM
TrackBack URL: http://www.typepad.com/services/trackback/6a00d8341c7bd453ef00d83482d1a769e2
Listed below are links to weblogs that reference Temporary Word CommandBars: