Archive

Archive for the ‘MFC’ Category

Windows 7 Ribbon – Part 2 – How handle ribbon control events?

July 2nd, 2009 Sarath Comments

In this installement, let’s see how to handle the events of the ribbon control. I strongly reconmmend you to read the previous post on the basics of ribbon 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 hand`ler.

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 create new command handler by querying IID_PPV_ARGS intefac. 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 CRibbonImplementer class. So here we will be modifying the class. We’ll be creating the the handler

Step 1 – Include the generated .h file contains control IDs to the implementation .h/.cpp file of CRibbonImplementer

b1

Step 2 & 3 – Derive ribbon implementer class from IUICommandHandler and add the interface to COM Map

b2

Step 4 – Modify OnCreateUICommand function and add UI Handler on creating the control.

b3

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.b4

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.

b5

The full Source code is given below. There’s no change in the other part of source code.

[sourcecode language='cpp']
#include “stdafx.h”
#include
#include
#include
#include
// Step 1: Include menu ribbon resource.h
#include “MenuRibbonRes.h”

class CRibbonImplementer:
public CComObjectRootEx,
public IUIApplication,
// Step 2: derive fromm IUICommandHandler
public IUICommandHandler
{
public:
BEGIN_COM_MAP(CRibbonImplementer)
COM_INTERFACE_ENTRY(IUIApplication)
// Step 3: IUICommandHandler add in teh COM Map
COM_INTERFACE_ENTRY(IUICommandHandler)
END_COM_MAP()

STDMETHOD(OnCreateUICommand)(UINT32 nCmdID, __in UI_COMMANDTYPE typeID, __deref_out IUICommandHandler** ppCommandHandler)
{
// Step 4: IUICommandHandler
// if my button is being created, the handler is created and attached
if (nCmdID == cmdMyButton)
{
return QueryInterface(IID_PPV_ARGS(ppCommandHandler));
}
return E_NOTIMPL;
}

/* Step 5: Implement execute function.
This function will be called on clicking
the controls attached to command handler */
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;

}

// unimplemented methods
// Step 6: Implement Update Property interface as well
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;
}
};
[/sourcecode]

Windows 7 Ribbon – Part 1 – How to Integrate a Simple Ribbon to your MFC Application?

June 30th, 2009 Sarath Comments

The Office 2007 changed the the conventional menu to a new vibrant, beautiful, and useful(??) ribbons. After that many third party libraries (both commercial and non commercial) vendors provided components to integrate ribbons to our application. Finally Microsoft heed the MFC guys crying a loud to get support on ribbons. Microsoft included Ribbons and other office style controls with MFC Feature Pack for Visual Studio 2008.

The following figure depicts the anatomy of a typical Ribbon.

image

In the new version of Windows, Windows 7 , it supports ribbons natively and Microsoft allows us to create it using Ribbon Frame Work.  Few Accessories application like MS Paint, Wordpad etc. got UI lift with Windows Ribbons.

Developer can create ribbon using Ribbon Markup Language (similar to XML format). For the Windows Ribbon framework (Ribbon) to consume the Ribbon markup file, the markup file must be compiled into a binary format resource file. A dedicated Ribbon markup compiler, the UI Command Compiler (UICC), is included with the Microsoft Windows Software Development Kit (SDK) (7.0 or later) for this purpose. In addition to compiling the binary version of the Ribbon markup, the UICC generates an ID definition header file that exposes all markup elements to the Ribbon host application and a resource file that is used to link the binary markup to the host application at build time.

The workflow for the Ribbon is as follows

Ribbon-Flow

OK let’s create a simple ribbon step by step. You should have Windows 7 SDK installed and Visual Studio 2005 or above is required to compile this application. I’m taking a MFC Application do this instead of a Win32 application. I’m just creating a new MFC Dialog Based Application.

We can categorize the ribbon creation in to two categories.

  • XML Markup, used to define the Ribbon structure and organization of controls
  • C++ COM interfaces, used to initialize and handle events

Step 1: Create the XML file with your ribbon. Add this XML for the solution. The following XML is a simple ribbon contains the application a Tab,Group and a button inside it.

1

[sourcecode language='xml']









My Button
My Button











Why TRACE0, TRACE1, TRACE2 functions even TRACE macro can have variable arguments?

April 26th, 2009 Sarath Comments

I raised following question in stack overflow some time back.

It’s possible to use TRACE macro as printf like function (variable argument list) . If it supports this facility, then why it’s necessary to have TRACE0, TRACE1 and TRACE2 macros except they’re imposing restrictions on number of arguments. Again, I’d like to know if there are any advantages on restricting number of arguments for TRACE macro.

The viewpoints shared by the community members are.

  • MFC 4 did not have variadic TRACE statements. That was added in a later version. The old-style TRACEn macros are probably there for backward compatibility.
  • The other reason is readability. It isn’t necessary to have the other trace variants (trace1, trace2 etc), but specifying exact number of arguments for a trace function is more readable than infinite number of argument list using TRACE macro

Anyway trace macros are obsolete now. It’s recommended to use ATLTRACE macro instead of TRACE macros. OK here’s quick information on TRACE macros. (See the link above for more info)

To display messages from your program in the debugger Output window, you can use the ATLTRACE macro or the MFC TRACE macro. Like assertions, the trace macros are active only in the Debug version of your program and disappear when compiled in the Release version.

  • TRACE0   Takes a format string (Only) and can be used for simple text messages, which are dumped to afxDump.
  • TRACE1   Takes a format string plus one argument (one variable that is dumped to afxDump).
  • TRACE2   Takes a format string plus two arguments (two variables that are dumped to afxDump).
  • TRACE3   Takes a format string plus three arguments (three variables that are dumped to afxDump)
Categories: C++, Code, MFC Tags: , , ,