Windows Ribbon for WinForms, Part 4 – Application Menu with Buttons

23 בספטמבר 2009

6 תגובות

Before we start to use ribbon features, we must learn the basics of ribbon markup.

Commands and Views
A command is an action that is identified by a number, it can be opening the save-as dialog, printing the current document, closing the application, etc. every thing you can do in a function call.

A view is a graphical representation of [usually several] commands. It defines the type of controls used to activate the commands and their size, order and layout on screen.

So using commands and views is actually just another instance of the MVC design pattern, which allows us to separate business logic from presentation logic.

Now we will write a new WinForms application with ribbon that uses the application menu with simple buttons. We start this sample with the an empty WinForms project that already includes ribbon support (see previous post for details). On the next sections I’ll explain:

  • Commands part of the ribbon markup
  • Views part of the ribbon markup
  • code-behind, responding to ribbon events

As always, the entire code is available at windowsribbon.codeplex.com

General markup review
Just a reminder, our basic ribbon markup looks like this:

<?xml version='1.0' encoding='utf-8'?>
<Application xmlns='http://schemas.microsoft.com/windows/2009/Ribbon'>
  <Application.Commands>
  </Application.Commands>

  <Application.Views>
    <Ribbon>
    </Ribbon>
  </Application.Views>
</Application>

Defining Commands in Ribbon Markup
Following is a definition of some commands in ribbon markup:

<Application.Commands>
  <Command Name="cmdButtonNew"
           Id="1001"
           LabelTitle="&amp;New"
           LabelDescription="New Description"
           TooltipTitle="New"
           TooltipDescription="Create a new image.">
    <Command.LargeImages>
      <Image>Res/New32.bmp</Image>
    </Command.LargeImages>
    <Command.SmallImages>
      <Image>Res/New16.bmp</Image>
    </Command.SmallImages>
  </Command>
  
  <Command Name="cmdButtonOpen"
           Id="1002"
           LabelTitle="Open"
           LabelDescription="Open Description"
           TooltipTitle="Open"
           TooltipDescription="Open an existing image.">
    <Command.LargeImages>
      <Image>Res/Open32.bmp</Image>
    </Command.LargeImages>
    <Command.SmallImages>
      <Image>Res/Open16.bmp</Image>
    </Command.SmallImages>
  </Command>
  
  <Command Name="cmdButtonSave"
           Id="1003"
           LabelTitle="Save"
           LabelDescription="Save Description"
           TooltipTitle="Save"
           TooltipDescription="Save the current image.">
    <Command.LargeImages>
      <Image>Res/Save32.bmp</Image>
    </Command.LargeImages>
    <Command.SmallImages>
      <Image>Res/Save16.bmp</Image>
    </Command.SmallImages>
  </Command>
  
  <Command Name="cmdButtonExit"
           Id="1004"
           LabelTitle="Exit"
           LabelDescription="Exit Description"
           TooltipTitle="Exit"
           TooltipDescription="Exit application.">
    <Command.LargeImages>
      <Image>Res/Exit32.bmp</Image>
    </Command.LargeImages>
    <Command.SmallImages>
      <Image>Res/Exit16.bmp</Image>
    </Command.SmallImages>
  </Command>
</Application.Commands>

Explanation: here we define 4 different commands. Each command has properties assigned either by xml attributes or child elements. We use the following (full list is available at “Commands and Resources” on MSDN):

  • Name – this name is used later in the views section to reference to this command
  • Id – this is the ID of the command. We get it in code when a command an event occurs.
  • LabelTitle – the label title of the command
  • LabelDescription – the label description of the command
  • TooltipTitle – the tooltip title of the command
  • TooltipDescription – the tooltip description of the command
  • LargeImages – large image filename for the command, usually 32×32 pixels
  • SmallImages – small image filename for the command, usually 16×16 pixels

Setting shortcuts to menu items
Setting a key shortcut for a menu item is done by adding “&amp;" in LabelTitle before the letter you want as a shortcut (similar to shortcuts in the “old” menu system), see the LabelTitle of “New” command for example.

Some comments about image resources in Ribbon markup
The filename defined in the markup (like in LargeImages and SmallImages element), should be a valid (relative or full) path to a filename, otherwise the resource compiler (rc.exe) will output a compilation error: “error RC2135: file not found: <filename>”.

The image file format should be BMP with 32 BPP ARGB pixel format. Many image editing programs, like Microsoft Paint do not preserve the highest order 8-bit alpha channel when saving, thus creating only 24 bit images, the result is that the image will not appear at all.
Update (18.11.2009): convert2bmp is a tool that enables you to convert your images to the required format.

Under both images elements you can put several image files in different sizes, the ribbon framework will choose the best size according to the current DPI setting. For us, normal users, setting two images for 32×32 and 16×16 should be enough. For more information, see "Specifying Ribbon Image Resources" on MSDN.

Defining Views in Ribbon Markup
Following is a definition of the views part of our ribbon markup:

<Application.Views>
  <Ribbon>
    <Ribbon.ApplicationMenu>
      <ApplicationMenu>
        <MenuGroup>
          <Button CommandName='cmdButtonNew' />
          <Button CommandName='cmdButtonOpen' />
          <Button CommandName='cmdButtonSave' />
        </MenuGroup>
        <MenuGroup>
          <Button CommandName='cmdButtonExit' />
        </MenuGroup>
      </ApplicationMenu>
    </Ribbon.ApplicationMenu>
  </Ribbon>
</Application.Views>

Explanation: here we define an application menu that contains two menu groups and 4 buttons. The button CommandName attribute points to the command that this button should trigger upon click.

Handling Ribbon Events
Here will see how to handle the event of clicking of one of our menu buttons.

The following code should reside in our main form code file (form1.cs in my sample):

public enum RibbonMarkupCommands : uint
{
     cmdApplicationMenu = 1000,
     cmdButtonNew = 1001,
     cmdButtonOpen = 1002,
     cmdButtonSave = 1003,
     cmdButtonExit = 1004,
}

This is just a helper enum, to make the code more readable. Every command ID gets a readable symbol.
The important section is our new implementation of the IUICommandHandler.Execute function:

public HRESULT Execute(uint commandId, UI_ExecutionVerb verb, ref PropertyKey key, ref PropVariant currentValue, IUISimplePropertySet commandExecutionProperties)
{
    if ((commandId == (uint)RibbonMarkupCommands.cmdButtonNew) &&
        (verb == UI_ExecutionVerb.Execute))
    {
        MessageBox.Show("new button pressed");
    }
    return HRESULT.S_OK;
}

Update (18.11.2009): Handling ribbon events is now as simple as normal .NET events. Implementing IUICommandHandler by the user is no longer required.

private Ribbon _ribbon;
private RibbonButton _buttonNew;

public Form1()
{
    InitializeComponent();

    _ribbon = new Ribbon();
    _buttonNew = new RibbonButton(_ribbon, (uint)RibbonMarkupCommands.cmdButtonNew);

    _buttonNew.OnExecute += new OnExecuteEventHandler(_buttonNew_OnExecute);
}

void _buttonNew_OnExecute(PropertyKeyRef key, PropVariantRef currentValue, IUISimplePropertySet commandExecutionProperties)
{
    MessageBox.Show("new button pressed");
}

Naturally we added to the beginning of the file:

using RibbonLib;
using RibbonLib.Controls;
using RibbonLib.Controls.Events;
using RibbonLib.Interop;

So there you have it, a WinForms application with a Ribbon Application Menu.

image 

That’s it for now,
Arik Poznanski.

kick it on DotNetKicks.com Shout it

הוסף תגובה
facebook linkedin twitter email

כתיבת תגובה

האימייל לא יוצג באתר. (*) שדות חובה מסומנים

6 תגובות

  1. Hackp14 בדצמבר 2009 ב 22:07

    Hi there,

    i got a problem. The menu does not show me images. I'm using 32 Bit BMP converted from PNG using Photoshop.

    This is my code:


    Resources/openfolder32.bmp


    Resources/openfolder16.bmp

    Can you help me?

    להגיב
  2. arik15 בדצמבר 2009 ב 9:30

    First I recommend you test your app using images you KNOW should work, e.g. Images from the library's samples projects. This is to make sure the problem is with the images and not the application code / markup.

    If this works then probably the images are not in the proper format. You can use this small tool: http://blogs.microsoft.co.il/blogs/arik/archive/2009/10/04/how-to-convert-an-image-to-32-bit-bmp.aspx
    or any other you find on the internet.

    להגיב
  3. Jody10 במאי 2010 ב 6:42

    I've run into a complex issue as I don't think this concept is intended by the ribbon. I need to execute C# code-behind when a user clicks on a tab. I took a best efforts approach below, but I'm not able to figure out all the syntax to make this work. Would very much appreciate your guidance.

    public partial class Application : Form, IRibbonForm
    {
    private Ribbon _ribbon;
    private RibbonTab _TargetTab;

    public Application()
    {
    InitializeComponent();
    _ribbon = new Ribbon();
    _TargetTab= new RibbonTab(_ribbon,(uint RibbonMarkupCommands.CaseTab);
    _TargetTab.Execute(ExecutionVerb, PropertyKeyRef, PropVariantRef, IUISimplePropertySet);
    }

    void _TargetTabClicked(PropertyKeyRef key, PropVariantRef currentValue, IUISimplePropertySet commandExecutionProperties)
    {
    MessageBox.Show("Target Tab Selected!");
    }

    //More Code…
    }

    להגיב
  4. arik10 במאי 2010 ב 18:42

    Sorry, the Windows Ribbon Framework doesn't support this kind of event.
    So, the managed wrapper can't possibly support it either.

    להגיב
  5. Alejandro Ramirez24 באוגוסט 2011 ב 1:44

    Is it possible to disable the AplicationMenu on the Ribbon Control??

    להגיב
  6. arik25 באוגוסט 2011 ב 23:26

    Alejandro Ramirez, unfortunately no.
    The Ribbon API is somewhat limited and the feature you seek is not possible.

    להגיב