Few days back I had an interesting case where one of our customers wanted to switch the ribbon programmatically, from the surface it looks easy ... but unfortunately currently there is no programmatic way to do it.
So, I started digging for a prospective workaround ...
- OM doesn't give us anything
- Can't simply use win32 APIs as ribbon tab is not a "window"
The first piece of the "gyan" that I can use active accessibility for this issue was from http://blogs.msdn.com/oldnewthing/archive/2006/08/16/702526.aspx.
After looking at it I Started playing with "Active Accessibility" APIs. After some more trial and error it was clear that I'll need to use a combination of Win32 APIs and "Active Accessibility" APIs. Built a sample library which basically does the following:-
- Based on inputs it will try to find the window of a specific office program (excel, word, powerpoint, etc)
- Then it will get the ribbon object [EnumWindows]
- Then we’ll get the IAccessibile object for the ribbon object
- We’ll recurse through the IAccessibility tree and find the control that you specify
- We’ll execute its default action (in case of ribbon tabs the default action is switch, for buttons it’s click and for the dropdowns it’s drop)
I also commented the code (question for you .. is commenting code painful for you? ..I mean, are you like me 🙂 ?) so that you can understand the code flow accurately. Download the attachment and have fun!! 🙂
If I get some questions around the sample, I'll post some examples on how to use it, here is a quick sample of using it from a windows form
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim o As New OfficeAccWraper
o.App = OfficeAccWraper.OfficeApp.MicrosoftWord2007
o.Command = "View"
Here is a quick FAQ:
Q: Is it a production code?
A: Absolutely not! it's a sample... just tells you how to do the stuff. Customize it to your needs and test it well before putting it to the production.
Q: Such a big sample! just for switching the ribbon tabs ? Am I missing something?
A: Yes, you are ... using this sample, you can executedefaultaction for any of the ribbon controls (e.g. maybe you want to switch a ribbon tab programmatically or you might want to do switch a ribbon or you might want to execute the commands that are in the "office menu")
Q: Is is a supported sample?
A: No, as I explained before, It's a sample, and provided as-is, without any help or support of any kind (no warranty ..no guaranty .. no liability etc.), but feels free to send me an email, if there is something that I can help with, I'll do it.
Q: What else can I do with it ? Is it just for Office?
A: You can use it for any application as long as it uses IAccessible control, how will the application behave? I don't know ..haven't tested .. you'll need to try (and let me know, if possible :))
Q: I see that it has two classes, one of them wraps the API calls and the other one uses this class and adds the office specific stuff why two classes? why not just one?
A: there were a few reasons ranging from good design to usability, but one of the most important reason was this, that I wanted this sample to be usable without office also, so if you want to use it for other applications, you'll just need to use the class which wraps the API calls)
Q: I see that it has two method with a similar name GetTopWindow and GetTopWindow2. I also see that you are using the first one in your office wrapper class. So, where do you use GetTopWindow2?
A: Nowhere. Actually, after designing the library I realized that there is one more way of getting a top level window, where I don't need to use FindWindow. So, I quickly included it in the library .. Tested using it and everything seems to work fine. But, finally I had to zero on one method so choose FindWindow (no specific reason). You an use GetTopWindow2 if you you are writing a wrapper for some other application. You can even modify the existing code and start using GetTopWindow2. Your choice ..!
Q: You are passing "View" in o.command. How do I know that what should I pass?
A: Good Question! you need to pass the "accessible name" of the control. For Office, I've noticed that for most of the controls the name that is shown in the tooltip, is the "accessible name". For the ribbon tabs, the caption is the "accessible name". But, for exactly knowing what do you need to pass you might want to use "AccExplorer32". Just drag the crosshair over the object and see the name, simple 🙂 . Download it from Download details- Active Accessibility 2.0 SDK Tools
Q: Where can I get more details about "Active Accessibility"
A: Here are some links that you might find useful:
- Microsoft Active Accessibility
- Microsoft Active Accessibility- Architecture
- Download details- Active Accessibility 2.0 Software Development
- Active Accessibility-Compliant Apps Give Programmers New Tools