Windows Ribbon for WinForms,第 15 部分 – 将 Ribbon 用作外部 DLL





5.00/5 (12投票s)
在本文中,我将介绍如何从外部 DLL 加载 ribbon 资源。
这系列 CodeProject 文章基于我首先在我的 博客上发表的一系列帖子。
使用 Windows Ribbon for WinForms 变得容易多了。
警告:枯燥的文章。 讨论了 ribbon 库中的更改及其原因。
引言
首先,请允许我请求您的原谅。 我正在尝试创建一个易于使用的库,因此对库的最后一次更改不向后兼容。 也就是说,类名和接口已更改。 请放心,我所做的每一项更改都使该库更易于使用。 但是,对于所有已经开始使用该库的人,我说:对不起。[这就是你使用BETA项目的结果。]
那么,发生了什么变化?
类名
我已将“Ribbon”前缀添加到所有 ribbon 控件辅助类。 这是为了防止与标准的 WinForms 控件(如 Button、ComboBox 等)发生冲突。
是的,我知道,这就是我们拥有命名空间的原因。 但是,拥有同时包含按钮和 ribbon 按钮的 WinForms 项目的情况并不少见。 发生这种情况时,用户无法添加“using RibbonLib.Controls;
”,因此几乎每一行都充满了“RibbonLib.Controls”前缀,例如
RibbonLib.Controls.Button ribbonButton =
new RibbonLib.Controls.Button(_ribbon, commandId);
而不是
RibbonButton ribbonButton = new RibbonButton(_ribbon, commandId);
IUICommandHandler 实现
我已将 IUICommandHandler
(Execute
和 UpdateProperty
函数)的通用实现添加到 Ribbon
类,以便用户不再需要实现这些方法。 这意味着用户不再需要在 Form
类中编写以下代码
public HRESULT Execute(uint commandId, ExecutionVerb verb, PropertyKeyRef key,
PropVariantRef currentValue, IUISimplePropertySet commandExecutionProperties)
{
switch (commandId)
{
case (uint)RibbonMarkupCommands.cmdDropDownColorPickerGroup:
_groupColors.Execute(verb, key, currentValue, commandExecutionProperties);
break;
case (uint)RibbonMarkupCommands.cmdButtonsGroup:
_groupButtons.Execute(verb, key, currentValue, commandExecutionProperties);
break;
case (uint)RibbonMarkupCommands.cmdButtonListColors:
_buttonListColors.Execute(verb, key, currentValue, commandExecutionProperties);
break;
case (uint)RibbonMarkupCommands.cmdDropDownColorPickerThemeColors:
_themeColors.Execute(verb, key, currentValue, commandExecutionProperties);
break;
case (uint)RibbonMarkupCommands.cmdDropDownColorPickerStandardColors:
_standardColors.Execute(verb, key, currentValue, commandExecutionProperties);
break;
case (uint)RibbonMarkupCommands.cmdDropDownColorPickerHighlightColors:
_highlightColors.Execute(verb, key, currentValue, commandExecutionProperties);
break;
}
return HRESULT.S_OK;
}
public HRESULT UpdateProperty(uint commandId, ref PropertyKey key,
PropVariantRef currentValue, ref PropVariant newValue)
{
switch (commandId)
{
case (uint)RibbonMarkupCommands.cmdDropDownColorPickerGroup:
_groupColors.UpdateProperty(ref key, currentValue, ref newValue);
break;
case (uint)RibbonMarkupCommands.cmdButtonsGroup:
_groupButtons.UpdateProperty(ref key, currentValue, ref newValue);
break;
case (uint)RibbonMarkupCommands.cmdButtonListColors:
_buttonListColors.UpdateProperty(ref key, currentValue, ref newValue);
break;
case (uint)RibbonMarkupCommands.cmdDropDownColorPickerThemeColors:
_themeColors.UpdateProperty(ref key, currentValue, ref newValue);
break;
case (uint)RibbonMarkupCommands.cmdDropDownColorPickerStandardColors:
_standardColors.UpdateProperty(ref key, currentValue, ref newValue);
break;
case (uint)RibbonMarkupCommands.cmdDropDownColorPickerHighlightColors:
_highlightColors.UpdateProperty(ref key, currentValue, ref newValue);
break;
}
return HRESULT.S_OK;
}
新的实现位于 Ribbon
类中,它只是根据命令 ID 将调用委托给正确的 ribbon 控件
public virtual HRESULT Execute(uint commandID, ExecutionVerb verb, PropertyKeyRef key,
PropVariantRef currentValue,
IUISimplePropertySet commandExecutionProperties)
{
if (_mapRibbonControls.ContainsKey(commandID))
{
_mapRibbonControls[commandID].Execute(verb, key, currentValue,
commandExecutionProperties);
}
return HRESULT.S_OK;
}
public virtual HRESULT UpdateProperty(uint commandID, ref PropertyKey key,
PropVariantRef currentValue,
ref PropVariant newValue)
{
if (_mapRibbonControls.ContainsKey(commandID))
{
_mapRibbonControls[commandID].UpdateProperty(ref key, currentValue,
ref newValue);
}
return HRESULT.S_OK;
}
_mapRibbonControls
是一个内部字典,其中包含用户在主窗体中创建的所有 ribbon 控件辅助类。
注意:我已将这些函数设为 virtual
,以便如果某些用户想要直接访问来自 ribbon 框架的通知,他们仍然可以通过从 Ribbon
类派生并覆盖这些方法来获取它们。
支持 Ribbon 外部 DLL
现在,您可以将 ribbon 资源驻留在外部 DLL 中,而不是像原生资源一样驻留在应用程序可执行文件中。 对于需要原生资源用于其他用途(例如设置应用程序图标)的开发人员来说,这个问题是一个问题。
事实上,我已经将其设置为 ribbon 的默认行为。 因此,现在,当您调用最简单的 Ribbon.InitFramework
形式时,ribbon 库会尝试从 *your_app_name.ribbon.dll* 加载 ribbon,并且只有在找不到此文件时,才会恢复到以前的行为,即尝试从您的可执行原生资源加载 ribbon。
当然,您可以提供自己的 DLL 名称来加载,甚至可以自己加载它并将 DLL 句柄(=LoadLibrary
返回的值)传递给 Ribbon.InitFramework
的不同重载。 这允许您实现自定义 ribbon 加载机制,如果您希望在不同的场景中加载不同的 ribbon,例如,添加本地化支持(不同的区域设置有不同的 ribbon),这将非常有用。
对于 ribbon 库的用户来说,这意味着他需要在预构建事件中添加一个步骤。 此步骤将从上一步创建的资源文件创建 ribbon 资源 DLL。 因此,使用 ribbon 库的项目的预构建事件现在是
"%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")"
我知道,这看起来像一堆垃圾,但实际上写的是
- UICC - 请将 RibbonMarkup.xml 转换为 RibbonMarkup.rc
- rc - 请将 RibbonMarkup.rc 转换为 RibbonMarkup.res
- link - 请将 RibbonMarkup.res 转换为 YourAppName.ribbon.dll
我已经更新了所有 ribbon 库示例以使用 ribbon 资源 DLL。
目前就到这里为止。