A comment on RibbonX callbacks

I found this kind of interesting, but somewhat strange...

A couple of nights ago I spent a significant amount of wasted time trying to get a callback to work in Visual Studio 2005. The problem was that I was trying to adapt my Dynamic Menu example to VB.Net, and the callback signatures for VB.Net and VBA are different. That's not really a big secret, and most of the callback signatures (in VB.Net, VBA, C# and C++) can be found in MSDN's Customizing the Office (2007) Ribbon User Interface for Developers (Part 3 of 3) article. Most, but not all currently.

To my chagrin, there was at least one callback signature missing... the getContent callback. For populating the dynamicMenu control, this is essential. That omission has been brought to Microsoft's attention, and hopefully the article will be updated soon.

Now, what's interesting about all of this... here's the signatures:

[vb]'This is the VB.Net callback signature
Function GetContent(ByRef control As Office.IRibbonControl) As String

'This is the VBA callback signature
Sub GetContent(control As Office.IRibbonControl, ByRef returnedVal)[/vb]

I'm fairly comfortable programming in VBA, but to me the VB.Net callback is far more intuitive to what I would have expected. In truth, despite working with the VBA signature for a while, I still scratched my head on why I was setting the value of "returnedVal" to a parameter. I knew that it was working, but was not sure why it was not looking like the VB.Net version, and why it was working.

The fact that it works makes sense, though, once you realize what is happening. I should have seen this way earlier, but I've never passed parameters like this. For my own purposes, I think I would have realized what was going on if the VBA version was written as:

[vb]Sub GetContent(ByVal control As Office.IRibbonControl, ByRef returnedVal)[/vb]

Do you see it? I added the ByVal keyword to the first control. To me, this would have probably alerted me to consider this... It's the ByRef keyword that does it.

By default, all objects are passed to and from subroutines and functions ByVal, and the keyword is therefore usually omitted. The key difference between ByVal and ByRef, though, is that when you pass a parameter ByVal, a copy of the object is passed, not the original object. This means that anything you do to the object is done on the copy only, and when the procedure or function ends, the temporary object goes out of scope and the changes are lost. By contrast, when you pass a parameter ByRef, it passes the original variable. Any changes made to that variable are done on the original, and this is how the callback works... changes are made to the original "returnedVal" object that was passed as a parameter ByRef to the subroutine.

Personally, I don't really follow why the VBA callbacks would have been set up as subroutines with the "returnedVal" object passed ByRef. To me this seems like the perfect use for a function, which is obviously the route that Microsoft decided to take with VB.Net.

Why the difference? Is there a good reason why they would choose to go one route with VBA vs the other with VB.Net?

If you have a comment or question about the blog post content, please feel free to post it here. If you need help adapting this solution to your own needs, please post in our free help forum.

Your email address will not be published. Required fields are marked *