在开始使用功能区特性之前,需要学习功能区标记的基础。命令和视图是功能区的核心概念。
命令(Command)是可以通过编号识别的操作,比如打开“另存为”对话框、打印当前文档、关闭应用程序等——所有可以通过函数调用来完成的操作。
视图(View)是命令的图形表示,通常包含多个命令。它定义了用于激活命令的控件类型以及它们在屏幕上的大小、顺序和布局。
使用命令和视图实际上是MVC设计模式的另一个实例,它允许将业务逻辑与表示逻辑分离。
现在,将编写一个新的WinForms应用程序,它使用带有简单按钮的应用菜单的功能区。从已经包含功能区支持的空WinForms项目开始(有关详细信息,请参见前面的帖子)。在接下来的部分中,将解释:
整个代码可以在windowsribbon.codeplex.com上找到。
基本功能区标记如下所示:
<?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>
以下是功能区标记中一些命令的定义:
<Application.Commands>
<Command Name='cmdButtonNew' Id='1001' LabelTitle='&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>
在这里,定义了4个不同的命令。每个命令都通过XML属性或子元素分配了属性。使用以下属性(完整列表可在MSDN的“Commands and Resources”中找到):
为菜单项设置快捷键是通过在LabelTitle之前添加“&”来完成的,想要的字母作为快捷键(类似于“旧”菜单系统中的快捷方式),例如“New”命令的LabelTitle。
在标记中定义的文件名(如LargeImages和SmallImages元素中的文件名)应该是一个有效的(相对或完整的)文件路径,否则资源编译器(rc.exe)将输出编译错误:“error RC2135: file not found:
图像文件格式应该是32 BPP ARGB像素格式的BMP。许多图像编辑程序,如Microsoft Paint在保存时不保留最高阶的8位alpha通道,因此只创建24位图像,结果是图像根本不会出现。
更新(18.11.2009):convert2bmp是一个工具,它允许将图像转换为所需的格式。
在两个图像元素下,可以放置不同大小的几个图像文件,功能区框架将根据当前的DPI设置选择最佳大小。对于普通用户来说,设置32x32和16x16的两个图像应该足够了。有关更多信息,请参见MSDN上的“SpecifyingRibbonImage Resources”。
以下是功能区标记中视图部分的定义:
<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>
在这里,定义了一个包含两个菜单组和4个按钮的应用菜单。按钮的CommandName属性指向点击时应该触发的命令。
在这里,将看到如何处理点击菜单按钮之一的事件。
以下代码应该位于主窗体代码文件(form1.cs)中:
public enum RibbonMarkupCommands : uint
{
cmdApplicationMenu = 1000,
cmdButtonNew = 1001,
cmdButtonOpen = 1002,
cmdButtonSave = 1003,
cmdButtonExit = 1004,
}
这只是一个辅助枚举,使代码更具可读性。每个命令ID都有一个可读的符号。
重要的部分是新的IUICommandHandler.Execute函数的实现:
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;
}
更新(18.11.2009):处理功能区事件现在和普通的.NET事件一样简单。不再需要用户实现IUICommandHandler。
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");
}
自然地,在文件的开头添加了:
using RibbonLib;
using RibbonLib.Controls;
using RibbonLib.Controls.Events;
using RibbonLib.Interop;