Introduction
This series of CodeProject articles is based on a series of posts I've first published on my blog.
So, let's see how to use the Ribbon class to add ribbon support to an empty WinForms application.
Step 0 - Download Windows Ribbon for WinForms
As I've mentioned in my previous posts, you can download the code for my ribbon wrapper library along with numerous samples (currently, one..) from windowsribbon.codeplex.com. Also, I remind you to download the helper library, Windows API Code Pack. Update (18.11.2009): The project doesn't depend anymore on Windows API Code Pack.
In this post, I'll review how to create your first, ribbon-enabled WinForms application. The result is the sample application "01-AddingRibbonSupport", included on the site.
Step 1 - Reference Windows Ribbon for WinForms
Create a new C# WinForms application, and add a reference to our developed library, Ribbon.dll.
Also, add to your main form (form1.cs) the following lines:
using RibbonLib;
using RibbonLib.Interop;
public partial class Form1 : Form, IRibbonForm
{
private Ribbon _ribbon = new Ribbon();
...
Step 2 - Add ribbon markup XML file
Add an empty file named RibbonMarkup.xml to the project. Set the file text to the following:
='1.0'='utf-8'
<Application xmlns='http://schemas.microsoft.com/windows/2009/Ribbon'>
<Application.Commands>
</Application.Commands>
<Application.Views>
<Ribbon>
</Ribbon>
</Application.Views>
</Application>
Right click on the editor where RibbonMarkup.xml is opened, and click Properties. Now, set the Schemas property to: C:\Program Files\Microsoft SDKs\Windows\v7.0\Bin\UICC.xsd. This will [visual] assist you in the future while editing the ribbon markup file (try Ctrl+Space on the XML editor to see the ribbon markup syntax).
Note: this is the moment where some of you will discover they didn't install Windows 7 SDK, so go ahead and fix it, I'll wait.
Step 3 - Set UI compiler to compile markup during build
Step 3.1 - Set pre-build events
Go to: Project Properties -> Build Events -> Pre-build event command line. Add the following three lines:
"%PROGRAMFILES%\Microsoft SDKs\Windows\v7.0\Bin\UICC.exe" "$(ProjectDir)RibbonMarkup.xml"
"$(ProjectDir)RibbonMarkup.bml" /res:"$(ProjectDir)RibbonMarkup.rc"
"%PROGRAMFILES%\Microsoft SDKs\Windows\v7.0\Bin\rc.exe" /v "$(ProjectDir)RibbonMarkup.rc"
cmd /c "("$(DevEnvDir)..\..\VC\bin\vcvars32.bat") && ("$(DevEnvDir)..\..\VC\bin\link.exe"
/VERBOSE /NOENTRY /DLL /OUT:"$(ProjectDir)$(OutDir)$(TargetName).ribbon.dll"
"$(ProjectDir)RibbonMarkup.res")"
Explanation: The first line compiles the ribbon markup file to a binary compressed format, along with a small RC file that describes it. The second line creates a native Win32 resource file to be attached to the project native resources. The third line creates a resource DLL from the native Win32 resource file.
Step 3.2 - Compile
Compile, in order to invoke the pre-build events.
Update (18.11.2009): Step 3.3 is no longer needed since the resource is loaded from the resource DLL.
Step 3.3 - Add native resource
Go to: Project Properties -> Application -> Resources -> Resource File. Set Resource file to point to: RibbonMarkup.res. When it says it can't find the file, close the Properties window anyway. It will save and find the file. If you wish to be on the safe side, just set the Resource file to the full path of the file (which is dependent on your project location).
Step 4 - Implement IRibbonForm
Have your main form implement the IRibbonForm
interface, which is defined in Ribbon.dll; you can follow the following guidelines:
- The Ribbon framework needs the main form window handle for initialization, hence:
public IntPtr WindowHandle
{
get
{
return this.Handle;
}
}
The Ribbon framework will partly hide your form, unless you write some code that repositions your controls according to the ribbon current height. A simple way of doing this is adding a SplitContainer
control to the main form and setting the following properties (you should change them using the GUI properties, not by code):
this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
this.splitContainer1.FixedPanel = System.Windows.Forms.FixedPanel.Panel1;
this.splitContainer1.IsSplitterFixed = true;
this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal;
this.splitContainer1.SplitterWidth = 1;
Now, all you need to do is put your form controls inside Panel2
of the SplitContainer
and update Panel1
height when the ribbon height changes (Panel1
act as a placeholder for the ribbon). The SplitContainer
will automatically reposition your controls accordingly. The actual update is done in the IRibbonForm
implementation:
public void RibbonHeightUpdated(int newHeight)
{
this.splitContainer1.SplitterDistance = newHeight;
}
The major part of the communication between the ribbon framework and your application is done by implementing the two following methods for which we'll initially give a default implementation. Update (18.11.2009): These functions should not be implemented by the user anymore, since the Ribbon
class now provides a general implementation, thus simplifying the use of the library.
public HRESULT Execute(uint commandId, ExecutionVerb verb,
PropertyKeyRef key, PropVariantRef currentValue,
IUISimplePropertySet commandExecutionProperties)
{
return HRESULT.S_OK;
}
public HRESULT UpdateProperty(uint commandId, ref PropertyKey key,
PropVariantRef currentValue, ref PropVariant newValue)
{
return HRESULT.S_OK;
}
Step 5 - Initialize the Ribbon Framework on application load
To initialize and destroy the ribbon framework, handle both the Load
and FormClosed
events of the Form, respectively:
private void Form1_Load(object sender, EventArgs e)
{
_ribbon.InitFramework(this);
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
_ribbon.DestroyFramework();
}
Enjoy your first Ribbon WinForms application
Note: If you run your application and don't see the ribbon, try to enlarge the window. The Windows ribbon has a feature that if the window size is too small, it doesn't show. Unfortunately, the Visual Studio default form size is too small.
That's it for now.