In this instalment, let’s see how to handle the events of the ribbon control. I strongly recommend you to read the previous post on the basics of ribbon about the way it’s being created. This is a continuation of the previous post.
To handle the events, the IUICommandHandler interface is implemented by the application and defines the Command handler methods for framework events. The following function has to be implemented in the derived class.
- Execute
Executes or previews the Commands bound to the Command handler.
- UpdateProperty
Sets a property value for a bound Command, for example, setting a Command to enabled or disabled depending on the state of a View.
For each Command in a View (Application.Views
in the XML file), the Ribbon framework requires a corresponding Command handler in the host application. A new handler or an existing handler must be bound to the Command through the IUIApplication::OnCreateUICommand notification method. This method is executed when the UI component is created. It’s possible to create a new command handler by querying IID_PPV_ARGS
interface. Any number of Commands can be bound to a Command handler.
The Command handler serves two purposes. First, it can update the values of properties for any command to which it is bound, such as setting a command to enabled or disabled. Second, it can execute or preview any commands to which it is bound.
In the previous instalment, we've seen the CRibbonImplementer
class. So here, we will be modifying the class. We'll be creating the handler.
Step 1
Include the generated .h file that contains control IDs to the implementation .h/.cpp file of CRibbonImplementer
:
Steps 2 & 3
Derive ribbon implementer class from IUICommandHandler
and add the interface to COM Map:
Step 4
Modify OnCreateUICommand
function and add UI Handler on creating the control.
Step 5
Add Execute handler to get notification when the button is clicked. This is like the normal message loop of a Win32 message loop system.
The Final Step (6)
It’s necessary to implement IUICommandHandler::UpdateProperty
as the base class doesn't provide any implementations. We can leave this interface
as unimplemented.
The full source code is given below. There’s no change in the other part of the source code.
#include "stdafx.h"
#include <atlbase.h>
#include <atlcom.h>
#include <initguid.h>
#include <uiribbon.h>
#include "MenuRibbonRes.h"
class CRibbonImplementer:
public CComObjectRootEx<CComMultiThreadModel>,
public IUIApplication,
public IUICommandHandler
{
public:
BEGIN_COM_MAP(CRibbonImplementer)
COM_INTERFACE_ENTRY(IUIApplication)
COM_INTERFACE_ENTRY(IUICommandHandler)
END_COM_MAP()
STDMETHOD(OnCreateUICommand)(UINT32 nCmdID, __in UI_COMMANDTYPE typeID,
__deref_out IUICommandHandler** ppCommandHandler)
{
if (nCmdID == cmdMyButton)
{
return QueryInterface(IID_PPV_ARGS(ppCommandHandler));
}
return E_NOTIMPL;
}
STDMETHODIMP Execute(UINT nCmdID,
UI_EXECUTIONVERB verb,
__in_opt const PROPERTYKEY* key,
__in_opt const PROPVARIANT* ppropvarValue,
__in_opt IUISimplePropertySet* pCommandExecutionProperties)
{
HRESULT hr = S_OK;
switch (verb)
{
case UI_EXECUTIONVERB_EXECUTE:
if (nCmdID == cmdMyButton)
{
MessageBox(NULL, _T( "Clicked on My Button!" ),
_T("My Button Execute"), MB_OK);
}
break;
}
return hr;
}
STDMETHODIMP UpdateProperty(UINT nCmdID,
__in REFPROPERTYKEY key,
__in_opt const PROPVARIANT* ppropvarCurrentValue,
__out PROPVARIANT* ppropvarNewValue)
{
return E_NOTIMPL;
}
STDMETHOD(OnViewChanged)(UINT32 nViewID, __in UI_VIEWTYPE typeID,
__in IUnknown* pView, UI_VIEWVERB verb, INT32 uReasonCode)
{
return E_NOTIMPL;
}
STDMETHOD(OnDestroyUICommand)(UINT32 commandId,
__in UI_COMMANDTYPE typeID,
__in_opt IUICommandHandler* pCommandHandler)
{
return E_NOTIMPL;
}
STDMETHODIMP UpdateProperty(UINT nCmdID,
__in REFPROPERTYKEY key,
__in_opt const PROPVARIANT* ppropvarCurrentValue,
__out PROPVARIANT* ppropvarNewValue)
{
return E_NOTIMPL;
}
};