2006-06-23
| Table of Contents: |
| Rate This Article: | Add This Article To: |
( Page 4 of 4 )
MS Office">
Deciphering Secret Messages
I recently needed to interact with Microsoft Office in an application I was writing, touching every Office product. I determined quite quickly that every Office application has a different set of rules. Word and Excel fall into one group, the remaining applications fall into another group.
Let's begin with Word and Excel: they provide an important lesson in using Spy++ effectively to create the custom applications you need. (Note that none of the information in this section comes with a guarantee. In addition, Microsoft could choose to change it at any time.)
In Globally Hooking Windows Messages in .NET, I showed you how to create your own custom messages. Microsoft and other vendors also use this technique. However, the use of a custom message in Word and Excel caused problems for me because the message is undocumented. To find it, I had to select the Registered option on the Message tab of the Message Options dialog box of Spy++. The Finder Tool focused the message logging on Word and its children. Figure 3 shows what I found.
Figure 3: Locating registered messages for other applications.
I used two strategies to discover what the contents of this display mean. First, I registered the WM_OBJECTSEL message with my application, just as I would for any custom messages that I wanted to receive from my own code. However, to receive this message, you rely on the WH_CALLWNDPROC hook, rather than other hooks described so far in this series.
Second, I tried to discover the meanings of the wParam and lParam entries shown in Figure 3. After a while, I discovered the wParam entry doesn't change, but the lParam entry does. The value in lParam is unique for every control. In addition, it was consistent across all of my test computers. Consequently, you can determine which control Office is accessing based on the lParam entry.
However, that presents another problem, because you can't be certain that the information you receive is from Office. That's when I noticed the instance handle for Office products is 0x30000000. By combining all three pieces of information, you can be sure that the message you receive is from Word or Excel. Viewing the messages that occur for specific events tells you which object numbers to use. For example, the Print dialog box for Word is 0x0024, while the same dialog box in Excel has an object value of 0x002D.
After I discovered the unique characteristics of Word and Excel, I thought other Office applications would use the same approach. Unfortunately, that assumption was wrong.
Other Office applications use a highly customized version of the common dialog box that doesn't follow all the standard common dialog box rules. You don't have to worry about any special messages, but these other dialog boxes rely on nuances of differences and they quickly will drive you crazy. For example, consider the simple issue of detecting the Number of Copies static control. You'll find three methods used to provide an accelerator key for this control: Number of &copies:, Num&ber of copies:, and N&umber of copies:, so you have to check for all three.
Outlook is a problem application. Outlook controls use an instance handle of 0x308E0000. Since you can use the standard WH_CBT hook to detect Outlook dialog boxes, you can also rely on the CBT_CREATEWND structure, which contains the CREATESTRUCT structure to obtain the instance handle directly. The CREATESTRUCT structure contains all of the information required to create the window, including the instance handle, size, position, style, and other information.
The Bottom Line
It's good that the .NET Framework hides many of the unsightly details of Windows operation from view, because you normally don't need to worry about them. You might not use thread or global hooks very often in your code, but they can help you create extremely robust applications when used correctly. Monitoring messages, interacting with windows, and understand in general how Windows works is a big plus when you create an application of any kind.
Hopefully, this article has shown you new possibilities in creating applications and understanding what the .NET Framework is doing for you in the background. These techniques can help you perform many tasks that you might have thought impossible.
![]() |
|


