Поделиться через


TN071: Реализация IOleCommandTarget в MFC

Примечание.

Следующее техническое примечание не было обновлено, поскольку сначала оно было включено в электронную документацию. В результате некоторые процедуры и разделы могут быть устаревшими или неверными. Для получения последних сведений рекомендуется выполнить поиск интересующей темы в алфавитном указателе документации в Интернете.

Интерфейс IOleCommandTarget позволяет объектам и их контейнерам отправлять команды друг другу. Например, панели инструментов объекта могут содержать кнопки для таких команд, как Print, Print Preview, SaveNewи Zoom. Если такой объект был внедрен в контейнер, поддерживающий IOleCommandTargetего, объект может включить свои кнопки и перенаправить команды в контейнер для обработки, когда пользователь щелкнул их. Если контейнер хотел, чтобы внедренный объект печатал себя, он может сделать этот запрос, отправив команду через IOleCommandTarget интерфейс внедренного объекта.

IOleCommandTarget — это интерфейс, похожий на автоматизацию, который используется клиентом для вызова методов на сервере. Однако использование IOleCommandTarget экономии затрат на выполнение вызовов через интерфейсы автоматизации, так как программисты не должны использовать обычно дорогостоящий Invoke метод IDispatch.

В MFC интерфейс используется активными серверами документов, IOleCommandTarget чтобы разрешить контейнерам активных документов отправлять команды на сервер. Класс сервера CDocObjectServerItemактивных документов использует карты интерфейса MFC (см. TN038 : MFC/OLE IUnknown Implementation) для реализации IOleCommandTarget интерфейса.

IOleCommandTarget также реализуется в COleFrameHook классе. COleFrameHook — это незадокументированные класс MFC, реализующий функциональные возможности окна кадров для контейнеров редактирования на месте. COleFrameHook также использует карты интерфейса MFC для реализации IOleCommandTarget интерфейса. COleFrameHookРеализация команд OLE пересылки в COleDocObjectItemконтейнеры производного активного IOleCommandTarget документа. Это позволяет любому контейнеру документов MFC Active получать сообщения от содержащихся серверов активных документов.

Команда OLE MFC Карты

Разработчики MFC могут воспользоваться преимуществами IOleCommandTarget карт команд OLE MFC. Карты команд OLE похожи на карты сообщений, так как их можно использовать для сопоставления команд OLE с функциями-членами класса, содержащего карту команд. Чтобы сделать эту работу, поместите макросы в карту команд, чтобы указать группу команд OLE, которую вы хотите обрабатывать, команду OLE и идентификатор сообщения WM_COMMAND , которое будет отправлено при получении команды OLE. MFC также предоставляет ряд предопределенных макросов для стандартных команд OLE. Список стандартных команд OLE, которые изначально были разработаны для использования с microsoft Приложение Office lications, см. в перечислении OLECMDID, которое определено в docobj.h.

Когда команда OLE получает приложение MFC, содержащее карту команд OLE, MFC пытается найти идентификатор команды и группу команд для запрошенной команды в карте команд OLE приложения. Если совпадение найдено, сообщение WM_COMMAND отправляется в приложение, содержащее карту команд с идентификатором запрошенной команды. (См. описание ON_OLECMD ниже.) Таким образом команды OLE, отправленные в приложение, превратятся в WM_COMMAND сообщения MFC. Затем WM_COMMAND сообщения направляются через карты сообщений приложения с помощью стандартной архитектуры маршрутизации команд MFC.

В отличие от карт сообщений, карты команд OLE MFC не поддерживаются ClassWizard. Разработчики MFC должны добавить поддержку карты команд OLE и записи карты команд OLE вручную. Карты команд OLE можно добавить на серверы документов MFC Active в любом классе, который находится в цепочке маршрутизации сообщений WM_COMMAND во время активного документа в контейнере. К этим классам относятся классы приложения, производные от CWinApp, CView, CDocument и COleIPFrameWnd. В контейнерах активных документов карты команд 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
Указатель на GUID группы команд OLE. Этот параметр имеет значение NULL для стандартной группы команд OLE.

olecmdid
Идентификатор команды OLE вызываемой команды.

id
Идентификатор сообщения WM_COMMAND, отправляемого в приложение, содержащее карту команд при вызове этой команды OLE.

Используйте макрос ON_OLECMD в карте команд, чтобы добавить записи для команд OLE, которые требуется обрабатывать. При получении команд OLE они будут преобразованы в указанное сообщение WM_COMMAND и перенаправлены через карту сообщений приложения с помощью стандартной архитектуры маршрутизации команд MFC.

Пример

В следующем примере показано, как добавить функцию обработки команд OLE на сервер документов MFC Active для обработки команды OLE OLECMDID_PRINT . В этом примере предполагается, что вы использовали 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_FILE_PRINT для идентификатора WM_COMMAND. ID_FILE_PRINT — это стандартный идентификатор команды печати, используемый приложениями MFC, созданными приложением AppWizard:

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

Обратите внимание, что один из стандартных макросов команд OLE, определенных в afxdocob.h, может использоваться вместо макроса ON_OLECMD, так как OLECMDID_PRINT является стандартным идентификатором команды OLE. Макрос ON_OLECMD_PRINT выполнит ту же задачу, что и макрос ON_OLECMD, показанный выше.

Когда приложение-контейнер отправляет этому серверу команду OLECMDID_PRINT через интерфейс сервера IOleCommandTarget , обработчик команд печати 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();
}

См. также

Технические примечания по номеру
Технические примечания по категории