65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIconstarIcon

5.00/5 (12投票s)

2010年3月2日

Ms-PL

3分钟阅读

viewsIcon

35862

downloadIcon

2954

在本文中,我将介绍如何从外部 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 实现

我已将 IUICommandHandlerExecuteUpdateProperty 函数)的通用实现添加到 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。

目前就到这里为止。

© . All rights reserved.