适用于 WinForms 的 Windows 功能区,第二部分 - 基本功能区包装器






4.67/5 (17投票s)
在本文中,我将介绍适用于 Windows 7 功能区框架的基本 .NET 包装器。
引言
这系列 CodeProject 文章基于我首先在我的 博客上发表的一系列帖子。
今天,我们将开始看一些代码,但在开始之前,您可能想知道在哪里可以找到它。
“适用于 WinForms 的 Windows 功能区”代码的最新版本将在 http://windowsribbon.codeplex.com/。它将包含项目的最新代码版本以及如何使用其不同功能的示例。请注意,它基于 .Windows API Code Pack,因此,如果您打算编译代码,请确保您已安装它。
更新(2009 年 11 月 18 日):适用于 WinForms 的 Windows 功能区项目不再依赖于 Windows API Code Pack,因此下载它不是必须的。
让我们开始吧。
创建 .NET 包装器
从 .NET 使用 Windows 功能区所需的第一件事是将 C++ / COM 定义转换为 C# 定义。
与功能区相关的文件是:UIRibbon.idl、UIRibbonKeydef.h 和 UIRibbonPropertyHelpers.h。请注意,UIRibbon.h 没有价值,因为它是由 MIDL 编译器从 UIRibbon.idl 自动生成的。所有这些文件都随 Windows 7 SDK 一起安装。
我不会讨论转换的细节,因为它是一个非常机械的过程,只需更改每个 C++ 类型并将其转换为相应的 .NET 等效类型即可。如果您对这些细节感兴趣,关于 .NET 互操作性 有无数的信息来源。
遵循 Windows API Code Pack 的约定,文件 UIRibbon.idl 被转换为四个不同的文件
- RibbonProperties.cs - 包含功能区属性定义
- RibbonCOMGuids.cs - 包含所有功能区相关的 GUID
- RibbonCOMInterfaces.cs - 包含功能区接口定义
- RibbonCOMClasses.cs - 包含功能区类定义
这些文件是我对 Windows 功能区框架使用的 COM 接口和类型进行的转换。随着项目的继续,这些文件可能会发生变化,因为我肯定会遇到一些转换错误,而这些错误只有在我尝试使用某个特定功能时才会发现。最新的版本将是 CodePlex 上的版本。
Windows 功能区框架如何工作?
完整详细信息可在 MSDN 中找到,我建议阅读。在这里,我只会简要概述一下,以便我们都清楚。
要在您的应用程序中初始化功能区,您需要执行以下操作
- 使用类似 XAML 的标记设计您的功能区外观。
- 使用 Microsoft 功能区标记编译器编译您的类似 XAML 的标记,该编译器随 Windows 7 SDK 一起提供。
- 将标记编译器的二进制输出存储为应用程序的(非托管)资源。
- 在应用程序加载时,使用
CoCreateInstance
创建实现IUIFramework
接口的UIRibbonFramework
类。 - 调用
framework.Initialize
并将对您的IUIApplication
接口实现的引用与您的应用程序窗口的HWND
一起传递。 IUIApplication
接口提供了一个回调,供功能区框架在其需要命令处理程序时调用,用于处理命令(由按钮、组合框和其他常用控件表示)。- 调用
framework.LoadUI
,它加载预编译的资源并显示实际的功能区。
到目前为止,我做了什么?
为了方便在 .NET 应用程序中使用功能区,我们将创建一个 单例 类,它将用作 Windows 功能区框架的 外观。更新(2009 年 11 月 10 日):Ribbon
类不再是单例,以支持在不同窗体上有两个功能区的应用程序。此类名为 Ribbon
,将负责初始化和与 Windows 功能区框架通信。
Ribbon
类将提供 IUIApplication
的实现,并处理所有 COM 细节。它本身无法提供的(信息)将由您实现的 IRibbonForm
接口(这是我发明的,所以不要去寻找它)提供。目的是让您的应用程序仅提供功能区运行所需的最少详细信息。
目前,IRibbonForm
定义如下
/// <summary>
/// IRibbonForm interface should be implemented
/// by the main form who want the ribbon
/// </summary>
public interface IRibbonForm : IUICommandHandler
{
/// <summary>
/// Getter for the main form window handle
/// </summary>
IntPtr WindowHandle { get; }
/// <summary>
/// Called when the ribbon height is changed,
/// allowing the form to reposition its controls so the ribbon doesn't hide them.
/// </summary>
/// <param name="newHeight">new height</param>
void RibbonHeightUpdated(int newHeight);
}
WindowHandle
属性用于为主窗口句柄提供功能区框架。
RibbonHeightUpdated
函数用于通知您的应用程序功能区的高度已更改。由于功能区的高度可能动态更改(例如,如果将窗口缩小到最小值,功能区将消失),您会收到此通知,以便您可以正确地重新组织窗体控件(以免功能区隐藏它们)。
关于 IRibbonForm
接口的最后一点是,它继承了 IUICommandHandler
。IUICommandHandler
是功能区框架处理命令事件所必需的接口。它为您的应用程序提供了知道按钮(或任何其他功能区控件)已被按下,因此需要您采取行动的方式。
更新(2009 年 11 月 18 日):Ribbon
类的更新版本提供了 IUICommandHandler
的实现,因此 IRibbonForm
不再继承自 IUICommandHandler
。
Ribbon
类目前公开两个方法
InitFramework
- 接收您的IRibbonForm
接口实现和将用于加载功能区配置的资源名称。DestroyFramework
- 清理代码,释放 Windows 功能区框架资源。
这些方法应分别在主应用程序窗体加载和关闭时调用。
摘要
这篇帖子写得有点长,所以我想就此打住。我已经将库代码放在 CodePlex 上,以及一个使用该代码创建简单 WinForms 功能区支持应用程序的示例。
在下一篇文章中,我将提供一些简单的细节,介绍如何使用我们到目前为止开发的内容来构建您的第一个 WinForms 功能区应用程序。
目前就到这里为止。