Как получить IDispatch документа Word или Excel из OCX

Переводы статьи Переводы статьи
Код статьи: 190985 - Vizualiza?i produsele pentru care se aplic? acest articol.
Развернуть все | Свернуть все

В этой статье

Аннотация

Довольно часто нуждаются в IDispatch контейнера элементов управления OLE. Вы часто можно получить IDispatch с помощью QueryInterface() из сразу доступные интерфейсы на сервере, такие как IOleClientSite. Однако для Некоторые серверы, такие как Microsoft Excel, этот подход не выполняется.

Другой способ получения интерфейса IDispatch — с помощью интерфейса API GetActiveObject() для Получите IDispatch сервер в таблице ROT. Однако этот метод требует необходимо получить CLSID или ProgID сервера. Кроме того, неоднозначная ситуация может возникнуть, где не может различить несколько экземпляры сервера.

В этой статье использует другой подход для получения интерфейса IDispatch, который работает с Microsoft Excel и Microsoft Word, даже если выполняется несколько экземпляров запущена.

Перечисленные ниже действия позволяют построить элемент управления, который можно получить IDispatch объект контейнера документа.

Дополнительная информация

Пошаговый пример

  1. Создание нового приложения MFC ActiveX ControlWizard с именем OffCntrDisp.
  2. Добавьте следующие переменные-члены класса производного COleControl:
          char m_szDocName[512];
          IDispatch *m_pDocDisp;
    					
    ПРИМЕЧАНИЕ: m_szDocName содержит имя документа, содержащего наш элемент управления и m_pDocDisp интерфейса IDispatch для этого документа.

  3. Добавьте следующий конец ваш производный COleControl Определение класса:
          // Interface Maps.
          protected:
             // IoleObject.
             BEGIN_INTERFACE_PART(MyOleObject, IOleObject)
                INIT_INTERFACE_PART(COffCtlDispCtrl, MyOleObject)
                STDMETHOD(SetClientSite)(LPOLECLIENTSITE);
                STDMETHOD(GetClientSite)(LPOLECLIENTSITE*);
                STDMETHOD(SetHostNames)(LPCOLESTR, LPCOLESTR);
                STDMETHOD(Close)(DWORD);
                STDMETHOD(SetMoniker)(DWORD, LPMONIKER);
                STDMETHOD(GetMoniker)(DWORD, DWORD, LPMONIKER*);
                STDMETHOD(InitFromData)(LPDATAOBJECT, BOOL, DWORD);
                STDMETHOD(GetClipboardData)(DWORD, LPDATAOBJECT*);
                STDMETHOD(DoVerb)(LONG, LPMSG, LPOLECLIENTSITE, LONG, HWND,
                LPCRECT);
                STDMETHOD(EnumVerbs)(IEnumOLEVERB**);
                STDMETHOD(Update)();
                STDMETHOD(IsUpToDate)();
                STDMETHOD(GetUserClassID)(CLSID*);
                STDMETHOD(GetUserType)(DWORD, LPOLESTR*);
                STDMETHOD(SetExtent)(DWORD, LPSIZEL);
                STDMETHOD(GetExtent)(DWORD, LPSIZEL);
                STDMETHOD(Advise)(LPADVISESINK, LPDWORD);
                STDMETHOD(Unadvise)(DWORD);
                STDMETHOD(EnumAdvise)(LPENUMSTATDATA*);
                STDMETHOD(GetMiscStatus)(DWORD, LPDWORD);
                STDMETHOD(SetColorScheme)(LPLOGPALETTE);
            END_INTERFACE_PART(MyOleObject)
    
            DECLARE_INTERFACE_MAP();
    					
    Она добавляется к переопределить реализацию по умолчанию COleControl IOleObject с вашего пользовательского MyOleObject.

  4. В вашей COleControl производного конструктора класса добавьте следующий код:
          m_pDocDisp = NULL;
  5. Только после следующей строки в OffCntrDispCtl.cpp:
          IMPLEMENT_OLECTLTYPE(COffCntrDispCtrl, IDS_OFFCNTRDISP,
    
           _dwOffCntrDispOleMisc)
    					
    Добавьте следующий код:
          BEGIN_INTERFACE_MAP(COffCntrDispCtrl, COleControl)
              INTERFACE_PART(COffCntrDispCtrl, IID_IOleObject, MyOleObject)
          END_INTERFACE_MAP()
    					
    Это, наряду с изменениями в шаге 3, переопределить его COleControl IOleObject.

  6. Код, добавленной на шаге 5 добавьте следующее:
          static char buf[8192];
          static void DoMsg(char *msg) {
             ::MessageBox(NULL, msg, "Message", MB_SETFOREGROUND);
          }
    
          static void DoErr(char *msg, long err) {
             static char errBuf[8192];
             sprintf(errBuf, "%s, Error: %ld (%08lx)", msg, err,err);
             ::MessageBox(NULL, errBuf, "Error", MB_SETFOREGROUND);
          }
    					
    Это полезные процедуры позже используется для отображения сообщения.

  7. Вставьте следующий код в конце вашего OffCntrDispCtl.cpp все файл:
          STDMETHODIMP COffCntrDispCtrl::XMyOleObject::SetHostNames(LPCOLESTR
          pwApp, LPCOLESTR pwObj)
          {
              METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
              ASSERT_VALID(pThis);
    
              // Convert OLESTR into ASCII string.
    
              WideCharToMultiByte(CP_ACP, 0, pwObj, -1, pThis->m_szDocName,
              512, NULL, NULL);
    
              // Get IDispatch.
              pThis->GetDocDispatch();
    
              // Test it out by getting the document name.
              pThis->TestDispatch();
    
              return S_OK;
          }
    
          STDMETHODIMP
          COffCntrDispCtrl::XMyOleObject::SetClientSite(LPOLECLIENTSITE
          pClientSite)
          {
              METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
              ASSERT_VALID(pThis);
              return pThis->m_xOleObject.SetClientSite(pClientSite);
          }
    
          STDMETHODIMP
          COffCntrDispCtrl::XMyOleObject::SetColorScheme(LPLOGPALETTE plp)
          {
              METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
              ASSERT_VALID(pThis);
              return pThis->m_xOleObject.SetColorScheme(plp);
          }
    
          STDMETHODIMP COffCntrDispCtrl::XMyOleObject::GetMiscStatus(DWORD
          dwAspect, DWORD* pdwStatus)
          {
              METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
              ASSERT_VALID(pThis);
              return pThis->m_xOleObject.GetMiscStatus(dwAspect, pdwStatus);
          }
    
          STDMETHODIMP
          COffCntrDispCtrl::XMyOleObject::EnumAdvise(LPENUMSTATDATA*
          ppenumAdvise)
          {
              METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
              ASSERT_VALID(pThis);
              return pThis->m_xOleObject.EnumAdvise(ppenumAdvise);
          }
    
          STDMETHODIMP COffCntrDispCtrl::XMyOleObject::Unadvise(DWORD
          dwConnection)
          {
              METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
              ASSERT_VALID(pThis);
              return pThis->m_xOleObject.Unadvise(dwConnection);
          }
    
          STDMETHODIMP COffCntrDispCtrl::XMyOleObject::Advise(LPADVISESINK
          pAdvSink, DWORD* pdwConnection)
          {
              METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
              ASSERT_VALID(pThis);
              return pThis->m_xOleObject.Advise(pAdvSink, pdwConnection);
          }
    
          STDMETHODIMP COffCntrDispCtrl::XMyOleObject::GetExtent(DWORD
          dwDrawAspect, LPSIZEL lpsizel)
          {
              METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
              ASSERT_VALID(pThis);
              return pThis->m_xOleObject.GetExtent(dwDrawAspect, lpsizel);
          }
    
    
          STDMETHODIMP COffCntrDispCtrl::XMyOleObject::SetExtent(DWORD
          dwDrawAspect, LPSIZEL lpsizel)
          {
              METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
              ASSERT_VALID(pThis);
              return pThis->m_xOleObject.SetExtent(dwDrawAspect, lpsizel);
          }
    
          STDMETHODIMP COffCntrDispCtrl::XMyOleObject::GetUserType(DWORD
          dwFormOfType, LPOLESTR* ppszUserType)
          {
              METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
              ASSERT_VALID(pThis);
    
              return pThis->m_xOleObject.GetUserType(dwFormOfType,
              ppszUserType);
          }
    
          STDMETHODIMP COffCntrDispCtrl::XMyOleObject::GetUserClassID(CLSID*
          pClsid)
          {
              METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
              ASSERT_VALID(pThis);
              return pThis->m_xOleObject.GetUserClassID(pClsid);
          }
    
          STDMETHODIMP COffCntrDispCtrl::XMyOleObject::IsUpToDate()
          {
              METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
              ASSERT_VALID(pThis);
    
              return pThis->m_xOleObject.IsUpToDate();
          }
    
          STDMETHODIMP COffCntrDispCtrl::XMyOleObject::Update()
          {
              METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
              ASSERT_VALID(pThis);
              return pThis->m_xOleObject.Update();
          }
    
          STDMETHODIMP COffCntrDispCtrl::XMyOleObject::EnumVerbs(LPENUMOLEVERB*
          ppenumOleVerb)
          {
              METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
              ASSERT_VALID(pThis);
    
              return pThis->m_xOleObject.EnumVerbs(ppenumOleVerb);
          }
    
          STDMETHODIMP COffCntrDispCtrl::XMyOleObject::DoVerb(LONG iVerb, LPMSG
          lpmsg, LPOLECLIENTSITE pActiveSite, LONG lindex, HWND hwndParent,
          LPCRECT lprcPosRect)
          {
              METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
              ASSERT_VALID(pThis);
              return pThis->m_xOleObject.DoVerb(iVerb, lpmsg, pActiveSite,
              lindex, hwndParent, lprcPosRect);
          }
    
          STDMETHODIMP COffCntrDispCtrl::XMyOleObject::GetClipboardData(DWORD
          dwReserved, LPDATAOBJECT *ppDataObject)
          {
              METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
              ASSERT_VALID(pThis);
              return pThis->m_xOleObject.GetClipboardData(dwReserved,
              ppDataObject);
          }
    
          STDMETHODIMP
          COffCntrDispCtrl::XMyOleObject::InitFromData(LPDATAOBJECT
          pDataObject, BOOL fCreation, DWORD dwReserved)
          {
              METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
              ASSERT_VALID(pThis);
              return pThis->m_xOleObject.InitFromData(pDataObject, fCreation,
              dwReserved);
          }
    
          STDMETHODIMP COffCntrDispCtrl::XMyOleObject::GetMoniker(DWORD
          dwAssign, DWORD dwWhichMoniker, LPMONIKER *ppmk)
          {
              METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
              ASSERT_VALID(pThis);
              return pThis->m_xOleObject.GetMoniker(dwAssign, dwWhichMoniker,
              ppmk);
          }
    
          STDMETHODIMP COffCntrDispCtrl::XMyOleObject::SetMoniker(DWORD
          dwWhichMoniker, LPMONIKER pmk)
          {
              METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
              ASSERT_VALID(pThis);
              return pThis->m_xOleObject.SetMoniker(dwWhichMoniker, pmk);
          }
    
          STDMETHODIMP COffCntrDispCtrl::XMyOleObject::Close(DWORD
          dwSaveOption)
          {
              METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
              ASSERT_VALID(pThis);
              return pThis->m_xOleObject.Close(dwSaveOption);
          }
    
          STDMETHODIMP
          COffCntrDispCtrl::XMyOleObject::GetClientSite(LPOLECLIENTSITE*
          ppClientSite)
          {
              METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
              ASSERT_VALID(pThis);
              return pThis->m_xOleObject.GetClientSite(ppClientSite);
    
          }
    
          STDMETHODIMP_(ULONG) COffCntrDispCtrl::XMyOleObject::Release()
          {
              METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
              ASSERT_VALID(pThis);
              return pThis->m_xOleObject.Release();
          }
    
          STDMETHODIMP_(ULONG) COffCntrDispCtrl::XMyOleObject::AddRef()
          {
              METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
              ASSERT_VALID(pThis);
              return pThis->m_xOleObject.AddRef();
          }
    
          STDMETHODIMP COffCntrDispCtrl::XMyOleObject::QueryInterface(REFIID
          iid, LPVOID* ppvObj)
          {
              METHOD_MANAGE_STATE(COffCntrDispCtrl, MyOleObject)
              ASSERT_VALID(pThis);
              return pThis->m_xOleObject.QueryInterface(iid, ppvObj);
          }
    					
    Это реализация IOleObject, который в основном делегирует все вызовы его реализация по умолчанию COleControl IOleObject, за исключением SetHostNames(). Треппинг SetHostNames() и сохранить имя документа, куда вставлен элемент управления.

    К сожалению Microsoft PowerPoint не вызывать этот метод, чтобы этот пример не будет работать с этим продуктом. Тем не менее Microsoft Powerpoint является одним экземпляром сервера, поэтому можно использовать GetActiveObject() однозначно получить указатель интерфейса IDispatch.
  8. Добавление следующих функций-членов в класс, производный от COleControl:
          void COffCntrDispCtrl::GetDocDispatch()
          {
              // No need, if we already have it.
              if(m_pDocDisp != NULL) return;
    
              // Get a BindCtx.
              IBindCtx *pbc;
              HRESULT hr = CreateBindCtx(0, &pbc);
              if(FAILED(hr)) {
                  DoErr("CreateBindCtx()", hr);
                  return;
              }
    
              // Get running-object table.
              IRunningObjectTable *prot;
              hr = pbc->GetRunningObjectTable(&prot);
              if(FAILED(hr)) {
                  DoErr("GetRunningObjectTable()", hr);
                  pbc->Release();
                  return;
              }
    
              // Get enumeration interface.
              IEnumMoniker *pem;
              hr = prot->EnumRunning(&pem);
              if(FAILED(hr)) {
                  DoErr("EnumRunning()", hr);
                  prot->Release();
                  pbc->Release();
                  return;
              }
    
              // Start at the beginning.
              pem->Reset();
    
              // Churn through enumeration.
              ULONG fetched;
              IMoniker *pmon;
              int n = 0;
              while(pem->Next(1, &pmon, &fetched) == S_OK) {
    
                  // Get DisplayName.
                  LPOLESTR pName;
                  pmon->GetDisplayName(pbc, NULL, &pName);
                  // Convert it to ASCII.
                  char szName[512];
                  WideCharToMultiByte(CP_ACP, 0, pName, -1, szName, 512, NULL,
                  NULL);
    
                  // Compare it against the name we got in SetHostNames().
                  if(!strcmp(szName, m_szDocName)) {
    
                      DoMsg("Found document in ROT!");
    
                      // Bind to this ROT entry.
                      IDispatch *pDisp;
                      hr = pmon->BindToObject(pbc, NULL, IID_IDispatch, (void
                      **)&pDisp);
                      if(!FAILED(hr)) {
                          // Remember IDispatch.
                          m_pDocDisp = pDisp;
    
                          // Notice...
                          sprintf(buf, "Document IDispatch = %08lx",
                          m_pDocDisp);
                          DoMsg(buf);
                      }
                      else {
                          DoErr("BindToObject()", hr);
                      }
                  }
    
                  // Release interfaces.
                  pmon->Release();
    
                  // Break out if we obtained the IDispatch successfully.
                  if(m_pDocDisp != NULL) break;
              }
    
              // Release interfaces.
              pem->Release();
              prot->Release();
              pbc->Release();
          }
    
          void COffCntrDispCtrl::TestDispatch()
          {
              ASSERT(m_pDocDisp);
    
              COleDispatchDriver doc(m_pDocDisp);
              DISPID dispID = 0;
              unsigned short *ucPtr = L"Name";
    
              // Get DISPID for Name.
              HRESULT hr = m_pDocDisp->GetIDsOfNames(IID_NULL, &ucPtr, 1,
              LOCALE_USER_DEFAULT, &dispID);
              ASSERT(!FAILED(hr));
    
    
              // Get Name property.
              CString name;
              doc.GetProperty(dispID, VT_BSTR, &name);
    
              AfxMessageBox(
                  CString("Document name is ") + name,
                  MB_SETFOREGROUND
              );
          }
    					
  9. Скомпилируйте!
Выполните эти шаги, чтобы протестировать элемент управления в Microsoft Excel 97.
  1. Для запуска Microsoft Excel 97.
  2. Вывести на экран Элементы управления панель инструментов (на Представление меню, нажмите кнопку Панели инструментов).
  3. Щелкните значок гаечного ключа & молоток правом на Элементы управления панели инструментов и выберите новый элемент управления; он должен быть вызван OffCntrDisp.
  4. Нарисуйте прямоугольник в лист, чтобы вставить элемент управления.РЕЗУЛЬТАТЫ: Вы должны увидеть элемент управления отображается и вскоре после этого, окно сообщения с «найденные документ в таблице ROT.» Далее вы должны увидеть отображение другого поля сообщения нечто похожее на «документ IDispatch = 0043bf8c.» Наконец вы Отобразится окно сообщения, информирующее о имя документа, где он был вставлен.
Выполните следующие далее действия, чтобы протестировать элемент управления в Microsoft Office Excel 2007.
  1. Запустите Excel 2007.
  2. Нажмите кнопку Разработчик Вкладка. Если Разработчик вкладка не отображается в ленте, выполните следующие действия, чтобы включить на вкладке.
    1. Нажмите кнопку Кнопки Microsoft Office, а затем нажмите кнопку Параметры Excel.
    2. Нажмите кнопку Популярные на вкладке и выберите Показывать вкладку "Разработчик" на ленте флажок.
    3. Нажмите кнопку ОК.
  3. В Элементы управления Группировать по Разработчик Щелкните Вставка.
  4. В группе Элементы управления ActiveX, нажмите кнопку Дополнительные элементы управления.
  5. В Дополнительные элементы управления диалоговое окно, нажмите кнопку OffCntrDisp.
  6. Нарисуйте прямоугольник в лист, чтобы вставить элемент управления. РЕЗУЛЬТАТЫ Элемент управления будет отображаться. Вскоре после этого появится окно сообщения, содержащее «Документ найденные в таблице ROT». После этого должно появиться другое окно сообщения об ошибке «документ IDispatch = 0043bf8c.» Наконец, вы увидите окно сообщения, указывающее имя документа, где он был вставлен.

Свойства

Код статьи: 190985 - Последний отзыв: 4 июня 2011 г. - Revision: 4.0
Информация в данной статье относится к следующим продуктам.
  • Microsoft Visual C++ 5.0 Enterprise Edition
  • Microsoft Visual C++ 5.0 Professional Edition
  • Microsoft Office Word 2007
  • Microsoft Word 2002 Standard Edition
  • Microsoft Word 2000 Standard Edition
  • Microsoft Word 97 Standard Edition
  • Microsoft Office Excel 2007
  • Microsoft Excel 2002 Standard Edition
  • Microsoft Excel 2000 Standard Edition
  • Microsoft Excel 97 Standard Edition
Ключевые слова: 
kbautomation kbhowto kbmt KB190985 KbMtru
Переведено с помощью машинного перевода
ВНИМАНИЕ! Перевод данной статьи был выполнен не человеком, а с помощью программы машинного перевода, разработанной корпорацией Майкрософт. Корпорация Майкрософт предлагает вам статьи, переведенные как людьми, так и средствами машинного перевода, чтобы у вас была возможность ознакомиться со статьями базы знаний KB на родном языке. Однако машинный перевод не всегда идеален. Он может содержать смысловые, синтаксические и грамматические ошибки, подобно тому как иностранец делает ошибки, пытаясь говорить на вашем языке. Корпорация Майкрософт не несет ответственности за неточности, ошибки и возможный ущерб, причиненный в результате неправильного перевода или его использования. Корпорация Майкрософт также часто обновляет средства машинного перевода.
Эта статья на английском языке:190985

Отправить отзыв

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com