Determine If Word is Installed
by Karl E. Peterson

June 2002 Issue  Download the original Classic VB code from this column.

Technology Toolbox: VB6, VB5, VB4/32

Q: Determine If Word is Installed
My application needs to know if Microsoft Word is installed, and if so, what version. I use this information to make the best possible use of automation, when available. Can I dig this out of the Registry somewhere?

A:
You could, but that sounds like an awful lot of work. You want to optimize automation, so let's use that technique to answer this question. The Application object exposed by Word offers a Version property, which you can query like this:

Public Function WordVersion() As String
   Dim obj As Object
   ' Quick test to determine if Word is
   ' installed, and return version.
   On Error Resume Next
   Set obj = _
      CreateObject("Word.Application")
   WordVersion = obj.Version
   Set obj = Nothing
End Function

This function relies on ignoring an error that's triggered if Word isn't installed. Test the return value first for length, as an empty string indicates no response from (or no creation of) the queried object. Now, you'll run into a slight problem if your specification calls for automating Word 95 as well, because that version used WordBasic rather than VBA. The good news is that newer versions of Word continue to expose the Word.Basic object. So, to be as universal as possible, you'd want to modify the preceding routine like this:

Public Function WordVersion() As String
   Dim obj As Object
   ' Quick test to determine if Word is
   ' installed, and return version.
   On Error Resume Next
   Set obj = CreateObject("Word.Basic")
   WordVersion = obj.AppInfo$(2)
   obj.AppClose
   Set obj = Nothing
End Function

Use either of these functions by examining the string returned. An empty string indicates no automatable version of Word is installed; otherwise, branch according to the string's contents (see Table 1). The Office group has gone out of its way to maintain backwards compatibility in this case. In fact, you can develop automation code for Word 95, even if it's not installed on your machine, by coding against the WordBasic model using whatever version of Word you do have installed.

I recommend using WordBasic only in cases where you find Word 95 installed, however. Using the newer Word.Application object is preferable, both in terms of speed and robustness of code. A further disincentive might be the fact that Microsoft no longer supports the WordBasic model actively. (My thanks to Jonathan West, Word MVP, for his valuable input to this response.) —K.E.P.

Q: Force Painting of Menu Checks
I like to set the Checked and Enabled properties of some dropdown menu items when the top-level menu is selected. For example, I use a checkmark to indicate that the current selection is Bold, and this attribute is far easier to test on demand than to track continuously. I've noticed that the checkmarks aren't always painted when the menu first drops. Toggling the Enabled property doesn't display this paint problem. As it is now, the user must wave the cursor over the item to force a repaint as the highlight bar moves over the item. What can I do programmatically to force VB to paint menu checkmarks properly?

A:
I've seen this same behavior, but never spent the time to track down exactly when it was occurring. In other words, thanks for asking, as this is something that's irritated me too! I wrote a little test applet that toggles the Checked property value of two first-level menu items each time the top-level menu is dropped:

Private Sub mMain_Click(Index As Integer)
   mTest(0).Checked = Not mTest(0).Checked
   mTest(1).Checked = Not mTest(1).Checked
End Sub

Some friends ran this sample on a number of systems, and we found the behavior you've described to be a common trait on Windows 2000 and Windows XP machines. It didn't matter what version of VB had compiled the test app. Your observation that the painting occurred predictably when Enabled was toggled led Jonathan Wood, VB MVP, to this crude, but effective, workaround:

Private Sub mMain_Click(Index As Integer)
   Dim i As Long
   For i = 0 To 1
      mTest(i).Checked = Not mTest(i).Checked
      If Check1.Value = vbChecked Then
         mTest(i).Enabled = Not mTest(i).Enabled
         mTest(i).Enabled = Not mTest(i).Enabled
      End If
   Next i
End Sub

Toggling each affected menu item's Enabled property twice—to ensure its return to its original state—did the trick. No observable menu flicker resulted, so it's probably advisable that we all get in the habit of using this hack anytime the Checked property is changed as the menu is dropped. You could fine-tune by testing for OS, but why go to that bother for something this simple? —K.E.P.


About the Author
Karl E. Peterson is a GIS analyst with a regional transportation-planning agency and serves as a member of the Visual Studio Magazine Technical Review and Editorial Advisory Boards. Online, he's a Microsoft MVP and a section leader on several VSM forums. Find more of Karl's VB samples at www.mvps.org/vb.