Share via


TN071:MFC IOleCommandTarget 实现

注意

以下技术说明在首次包括在联机文档中后未更新。 因此,某些过程和主题可能已过时或不正确。 要获得最新信息,建议你在联机文档索引中搜索热点话题。

IOleCommandTarget 接口使对象及其容器能够向彼此分发命令。 例如,对象的工具栏可能包含 PrintPrint PreviewSaveNewZoom 等命令的按钮。 如果这种对象嵌入到支持 IOleCommandTarget 的容器中,则该对象可以启用其按钮,并将命令转发到容器以在用户单击按钮时进行处理。 如果容器希望嵌入式对象打印自身,则它可以通过嵌入式对象的 IOleCommandTarget 接口发送命令,以此发出这种请求。

IOleCommandTarget 是类似于自动化的接口,因为客户端使用它在服务器上调用方法。 但是,使用 IOleCommandTarget 可以免除通过自动化接口发出调用所产生的开销,因为程序员不必使用 IDispatchInvoke 方法(该方法的开销通常很高)。

在 MFC 中,活动文档服务器使用 IOleCommandTarget 接口来允许活动文档容器向服务器分发命令。 活动文档服务器类 CDocObjectServerItem 使用 MFC 接口映射(请参阅 TN038:MFC/OLE IUnknown 实现)来实现 IOleCommandTarget 接口。

IOleCommandTarget 也在 COleFrameHook 类中实现。 COleFrameHook 是一个未记录的 MFC 类,它实现就地编辑容器的框架窗口功能。 COleFrameHook 也使用 MFC 接口映射来实现 IOleCommandTarget 接口。 COleFrameHookIOleCommandTarget 实现将 OLE 命令转发到 COleDocObjectItem 派生的活动文档容器。 这样,任何 MFC 活动文档容器就能从包含的活动文档服务器接收消息。

MFC OLE 命令映射

MFC 开发人员可以通过 MFC OLE 命令映射来利用 IOleCommandTarget。 OLE 命令映射类似于消息映射,因为它们可用于将 OLE 命令映射到包含命令映射的类的成员函数。 要做到这一点,请在命令映射中放置宏,以指定要处理的命令的 OLE 命令组、OLE 命令,以及在收到 OLE 命令时要发送的 WM_COMMAND 消息的命令 ID。 MFC 还为标准 OLE 命令提供许多预定义的宏。 有关最初设计用于 Microsoft Office 应用程序的标准 OLE 命令的列表,请参阅 docobj.h 中定义的 OLECMDID 枚举。

当包含 OLE 命令映射的 MFC 应用程序收到 OLE 命令时,MFC 会尝试在应用程序的 OLE 命令映射中查找所请求命令的命令 ID 和命令组。 如果找到匹配项,则向应用程序分发一条 WM_COMMAND 消息,其中包含命令映射以及所请求命令的 ID。 (请参阅下面的 ON_OLECMD 说明。)这样,分发到应用程序的 OLE 命令将由 MFC 转换为 WM_COMMAND 消息。 然后使用 MFC 标准命令路由体系结构通过应用程序的消息映射路由 WM_COMMAND 消息。

与消息映射不同,MFC OLE 命令映射不受 ClassWizard 支持。 MFC 开发人员必须手动添加 OLE 命令映射支持和 OLE 命令映射条目。 当活动文档在容器本地处于活动状态时,可将 OLE 命令映射添加到 WM_COMMAND 消息路由链中的任何类中的 MFC 活动文档服务器。 这些类包括派生自 CWinAppCViewCDocumentCOleIPFrameWnd 的应用程序类。 在活动文档容器中,OLE 命令映射只能添加到 COleDocObjectItem 派生类。 此外,在活动文档容器中,WM_COMMAND 消息仅分发到 COleDocObjectItem 派生类中的消息映射。

OLE 命令映射宏

使用以下宏将命令映射功能添加到类:

DECLARE_OLECMD_MAP ()

此宏位于包含命令映射的类的类声明中(通常在头文件中)。

BEGIN_OLECMD_MAP(theClass, baseClass)

theClass
包含命令映射的类的名称。

baseClass
包含命令映射的类的基类名称。

此宏标记命令映射的开头。 在包含命令映射的类的实现文件中使用此宏。

END_OLECMD_MAP()

此宏标记命令映射的末尾。 在包含命令映射的类的实现文件中使用此宏。 此宏必须始终遵循 BEGIN_OLECMD_MAP 宏。

ON_OLECMD(pguid, olecmdid, id)

pguid
指向 OLE 命令的命令组的 GUID 的指针。 对于标准 OLE 命令组,此参数为 NULL

olecmdid
要调用的命令的 OLE 命令 ID。

id
调用此 OLE 命令时要发送到包含命令映射的应用程序的 WM_COMMAND 消息的 ID。

使用命令映射中的 ON_OLECMD 宏为要处理的 OLE 命令添加条目。 收到 OLE 命令时,它们将转换为指定的 WM_COMMAND 消息,并使用标准 MFC 命令路由体系结构通过应用程序的消息映射进行路由。

示例

以下示例演示如何将 OLE 命令处理功能添加到 MFC 活动文档服务器,以处理 OLECMDID_PRINT OLE 命令。 此示例假设使用 AppWizard 生成了作为活动文档服务器的 MFC 应用程序。

  1. CView 派生类的头文件中,将 DECLARE_OLECMD_MAP 宏添加到类声明。

    注意

    使用 CView 派生类,因为它是 WM_COMMAND 消息路由链中的活动文档服务器中的类之一。

    class CMyServerView : public CView
    {
    protected: // create from serialization only
        CMyServerView();
        DECLARE_DYNCREATE(CMyServerView)
        DECLARE_OLECMD_MAP()
        // . . .
    };
    
  2. CView 派生类的实现文件中,添加 BEGIN_OLECMD_MAP 和 END_OLECMD_MAP 宏:

    BEGIN_OLECMD_MAP(CMyServerView, CView)
    
    END_OLECMD_MAP()
    
  3. 若要处理标准 OLE 打印命令,请将 ON_OLECMD 宏添加到命令映射,并指定标准打印命令的 OLE 命令 ID,以及 WM_COMMAND ID 的 ID_FILE_PRINT。 ID_FILE_PRINT 是 AppWizard 生成的 MFC 应用程序使用的标准打印命令 ID

    BEGIN_OLECMD_MAP(CMyServerView, CView)
        ON_OLECMD(NULL, OLECMDID_PRINT, ID_FILE_PRINT)
    END_OLECMD_MAP()
    

请注意,在 afxdocob.h 中定义的标准 OLE 命令宏之一可用于代替 ON_OLECMD 宏,因为 OLECMDID_PRINT 是标准 OLE 命令 ID。 ON_OLECMD_PRINT 宏将完成与上面所示的 ON_OLECMD 宏相同的任务。

当容器应用程序通过服务器的 IOleCommandTarget 接口向此服务器发送 OLECMDID_PRINT 命令时,将在服务器中调用 MFC 打印命令处理程序,导致服务器打印应用程序。 用于调用上述步骤中添加的打印命令的活动文档容器代码如下所示:

void CContainerCntrItem::DoOleCmd()
{
    IOleCommandTarget *pCmd = NULL;
    HRESULT hr = E_FAIL;
    OLECMD ocm={OLECMDID_PRINT, 0};

    hr = m_lpObject->QueryInterface(
        IID_IOleCommandTarget,reinterpret_cast<void**>(&pCmd));

    if (FAILED(hr))
        return;

    hr = pCmd->QueryStatus(NULL, 1, &ocm, NULL);

    if (SUCCEEDED(hr) && (ocm.cmdf& OLECMDF_ENABLED))
    {
        //Command is available and enabled so call it
        COleVariant vIn;
        COleVariant vOut;
        hr = pCmd->Exec(NULL, OLECMDID_PRINT,
            OLECMDEXECOPT_DODEFAULT, &vIn, &vOut);
        ASSERT(SUCCEEDED(hr));
    }
    pCmd->Release();
}

另请参阅

按编号列出的技术说明
按类别列出的技术说明