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

ATL COM 插件/插件框架,支持动态工具栏和菜单

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.86/5 (32投票s)

2004 年 12 月 3 日

3分钟阅读

viewsIcon

170845

downloadIcon

3185

一篇关于 ATL COM 插件/插件框架,支持动态工具栏和菜单的文章,基于 VC++ 插件架构。

链接

引言

为每个客户的需求量身定制产品是每个公司的梦想。但在实践中可能并非如此。这是因为在大多数情况下,需求会发生剧烈变化,以至于我们必须在代码级别进行更改,重新编译,测试,然后作为新版本发布。这种开发方式在项目成本和开发工作量方面效率不高。这就是 **Addin / Plugin** 架构的优势所在。在这篇文章中,我编写了一个 ATL COM Addin / Plugin Framework,**支持动态工具栏和菜单**。该框架实际上基于 VC++ 6.0 Addin Architecture,这是 Microsoft 在所有 MS Office 应用程序中使用的(不确定确切实现,只是猜测,因为我遵循了 VC++ Addin 向导生成的代码相同的路径)。一个不同之处在于,VC++ Addin 在添加菜单、其描述和其他详细信息时使用新行分隔的方式,而我使用 XML 格式来添加插件详细信息(不知道为什么 Microsoft 没有使用 XML?也许那时 **XML** 还没有标准化?或者有其他特定原因?),并使用 **Component Category** 对插件进行分类。点击**此处**查看我在本项目中使用的 XML 格式。如果您愿意,可以添加更多的属性作为叶节点(我遵循了将菜单属性作为节点放置的思路。或者您也可以以其他方式放置属性)。

背景

本文假设您对 COM 和 MFC 有基本了解。本文实际上是对 **Zac Howland** 撰写的精彩文章 使用组件类别构建可插入组件 - 第一部分 的延续。因此,建议用户在阅读我的文章之前先阅读这篇文章。

使用代码

随附的演示项目包含 3 个用 VC++ 6.0 编写的项目工作区。 **ProjectFramework** 应用程序负责加载所有插件、其菜单、工具栏和其他详细信息。该应用程序使用一个名为 **CAddinManager** 的核心类来进行各种插件操作。 **CAddinManager** 类的主要头文件如下所示。

class CAddinManager 
{
private:
    BOOL m_bLoadAllAdins;
    CArray<CAddinInfo,CAddinInfo> m_AddinInfoArray;
    CComPtr<IProjectFramework> m_ProjectFrameworkObject;
    HRESULT LoadAllAdins(BSTR strAddinLoadingInfo,
                         IProjectFramework* pProjectFramework);
 
public:
    BOOL InvokeAddinMenuItem(UINT iCommandID);
    BOOL SetAddinVisible(CString strAddinName, BOOL bVisible);
    const CAddinInfo& GetAddinInformation(UINT iCommandID);
    const CAddinCommadInfo& GetAddinCommadInfo(UINT iCommandID);
    CAddinCommadInfo GetAddinCommadInfo(long iAddinIndex,long lIndex);
    BOOL AddAddinCommandInfo(long iAddinIndex, 
                             CAddinCommadInfo AddinCommadInfo);
    BOOL SetAddinCount(long lCount);
    BOOL UnloadAllAddins();
    CAddinInfo GetAddinInfo(long iAddinIndex);
    BOOL SetAddinInfo(long iAddinIndex,CAddinInfo AddinInfo);
    long GetAddinCount();
    void SetLoadAllAddinStatus(BOOL bLoadAllAddins);
    virtual BOOL GetLoadAllAddinStatus();
    CAddinInfo GetAddinIffo(CLSID clsID);

    BOOL LoadAllAddins();
    BOOL SaveAddinDefaultSettings();
    BOOL LoadAddinDefaultSettings();
    
    CAddinManager();
    virtual ~CAddinManager();

};
此类使用许多其他相关类,例如 `CAddinInfo`,它包含每个插件的信息; `IProjectFramework`,这是 ProjectFramework 应用程序公开的接口;以及 `IProjectFrameworkAddin` 接口,这是每个插件都应该实现的。请参阅源代码以获取更多详细信息。应用程序构建所用的重要代码块如下所示。

在 CProjectFrameworkApp 中,静态声明一个 `CAddinManager` 变量。

static CAddinManager m_AddinManager;
static CProjectFrameworkView* m_pView;

in

BOOL CProjectFrameworkApp::InitInstance()
{
    ...
    if (!ProcessShellCommand(cmdInfo))
        return FALSE;
    ((CMainFrame*)m_pMainWnd)->LoadAditionalAccelerators();
}

在 `CMainFrame` 中

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
ON_WM_CREATE()
ON_COMMAND(ID_ADDIN_ADDINSETTINGS, OnAddinAddinsettings)
ON_WM_CLOSE()
ON_WM_MENUSELECT()
ON_WM_INITMENUPOPUP()
//}}AFX_MSG_MAP

ON_COMMAND_RANGE(PF_ADDIN_CMD_MIN_MSG_ID, PF_ADDIN_CMD_MAX_MSG_ID, 
OnAddinMenuItems) ON_UPDATE_COMMAND_UI_RANGE(PF_ADDIN_CMD_MIN_MSG_ID, PF_ADDIN_CMD_MAX_MSG_ID,
OnUpdateAddinMenuItems) ON_UPDATE_COMMAND_UI_RANGE(ID_FILE_NEW, ID_APP_ABOUT, OnUpdateMenuItems) ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, PF_MIN_MSG, PF_MAX_MSG, OnToolTipText) ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, PF_MIN_MSG, PF_MAX_MSG, OnToolTipText)
END_MESSAGE_MAP()

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
        return -1;


    //Load all addins
    if(CProjectFrameworkApp::m_AddinManager.LoadAddinDefaultSettings())
    {
        if(CProjectFrameworkApp::m_AddinManager.GetLoadAllAddinStatus())
        {
            CProjectFrameworkApp::m_AddinManager.LoadAllAddins(); 
        }
    }
    LoadAllAddinCommands();

    if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | 
                                         WS_VISIBLE | CBRS_TOP
                    | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY 
                     | CBRS_SIZE_DYNAMIC) 
        || !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
    {
        TRACE0("Failed to create toolbar\n");
        return -1; // fail to create
    }

    if (!m_wndStatusBar.Create(this) ||
        !m_wndStatusBar.SetIndicators(indicators,
                                      sizeof(indicators)/sizeof(UINT)))
    {
        TRACE0("Failed to create status bar\n");
        return -1; // fail to create
    }

    // TODO: Delete these three lines if you don't want the toolbar to
    // be dockable

    m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
    EnableDocking(CBRS_ALIGN_ANY);
    DockControlBar(&m_wndToolBar);

    //Remove File new and Open Commands
    RemoveCommands(ID_FILE_NEW);
    RemoveCommands(ID_FILE_OPEN);
    return 0;
}

关注点

此版本实现的功能有。

  1. 动态菜单。
  2. 动态工具栏。
  3. 帮助字符串和工具提示支持。
  4. 从插件菜单和工具栏调用插件中的方法。
  5. 通过从某个插件调用的对话框解释自动化支持(报表插件 -> 销售报表 -> 今日销售报表 Ctrl + B 菜单)。
  6. 隐藏菜单和工具栏按钮(例如:文件 -> 新建和打开)。
  7. 插件的键盘加速器支持。
  8. 加载/卸载插件。
  9. 连接点支持,用于从插件获取通知事件。

历史

  • 初始发布:2004 年 12 月 2 日
  • 添加了连接点支持:2004 年 12 月 10 日
© . All rights reserved.