Como obter o IDispatch de um documento Excel ou Word de um OCX

Traduções deste artigo Traduções deste artigo
ID do artigo: 190985 - Exibir os produtos aos quais esse artigo se aplica.
Expandir tudo | Recolher tudo

Neste artigo

Sumário

É comum para um controle OLE precisará IDispatch de seu recipiente. Você geralmente pode obter o IDispatch usando QueryInterface() de interfaces imediatamente acessíveis no servidor, como IOleClientSite. No entanto, para alguns servidores, como o Microsoft Excel, essa abordagem falha.

Outra maneira de obter o IDispatch é usando a API GetActiveObject() para obter o IDispatch do servidor do ROT. No entanto, este método requer que você deve poder obter CLSID ou ProgID do servidor. Além disso, ambíguas situações podem ocorrer onde você não pode distinguir entre várias instâncias do servidor.

Este artigo usa outra abordagem para obter o IDispatch, que funciona para o Microsoft Excel e Microsoft Word, mesmo quando estão executando várias instâncias.

As etapas listadas abaixo permitem que você criar um controle que pode obter o IDispatch do objeto de documento do recipiente.

Mais Informações

Exemplo da etapa por etapa

  1. Crie um novo aplicativo de MFC ActiveX WebAssistente chamado OffCntrDisp.
  2. Adicionar as seguintes variáveis membro à sua classe derivada de COleControl:
          char m_szDocName[512];
          IDispatch *m_pDocDisp;
    					
    Observação : m_szDocName mantém o nome do documento que contém nosso controle e m_pDocDisp é a interface IDispatch para o documento.

  3. Adicione o seguinte ao final de sua definição de classe derivada 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();
    					
    este é adicionado ao substituir implementação de padrão da COleControl de IOleObject com seu MyOleObject personalizado.

  4. No construtor da classe seu derivado COleControl, adicione o seguinte:
          m_pDocDisp = NULL;
  5. Logo após a seguinte linha no OffCntrDispCtl.cpp:
          IMPLEMENT_OLECTLTYPE(COffCntrDispCtrl, IDS_OFFCNTRDISP,
    
           _dwOffCntrDispOleMisc)
    					
    adicione o seguinte código:
          BEGIN_INTERFACE_MAP(COffCntrDispCtrl, COleControl)
              INTERFACE_PART(COffCntrDispCtrl, IID_IOleObject, MyOleObject)
          END_INTERFACE_MAP()
    					
    isso, junto com as modificações na etapa 3, substituir do COleControl IOleObject.

  6. Logo abaixo o código adicionado na etapa 5, adicione o seguinte:
          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);
          }
    					
    são úteis rotinas usadas posteriormente para exibir mensagens.

  7. Colar todos os o código a seguir no final do seu OffCntrDispCtl.cpp arquivo:
          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);
          }
    					
    esta é sua implementação do IOleObject, que delega todas suas chamadas para implementação de IOleObject do COleControl padrão, exceto para SetHostNames() principalmente. Você ajusta o registro SetHostNames() e armazena o nome do documento onde o controle é inserido.

    Infelizmente, o Microsoft PowerPoint não chamar esse método, para que este exemplo não trabalha com esse produto. No entanto, Microsoft PowerPoint é um servidor de single-instance, portanto, você poderia usar GetActiveObject() para obter o ponteiro IDispatch exclusivamente.
  8. Adicionar as seguintes funções de membro à sua classe derivada de 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. Compilação!
Siga estas etapas próxima para testar o controle no Microsoft Excel 97:
  1. Inicie o Microsoft Excel 97.
  2. Exibir a caixa de ferramentas de controle (no menu Exibir , clique em barras de ferramentas ).
  3. Clique no ícone extrema direita de martelo & chave inglesa na Ferramentas de controle e selecione o novo controle; ela deve ser chamada OffCntrDisp.
  4. Desenhe um retângulo na planilha para inserir o controle. resultados : você deve ver o controle aparecer e em breve posteriormente, uma caixa de mensagem com "Encontrado documento no ROT." Em seguida, você verá outra caixa de mensagem exibindo algo semelhante a "documento IDispatch = 0043bf8c." Finalmente, você verá uma caixa de mensagem informando do nome do documento onde ele foi inserido.
Siga estas etapas próxima para testar o controle no Microsoft Office Excel 2007:
  1. Inicie o Excel 2007.
  2. Clique na guia desenvolvedor . Se a guia desenvolvedor não estiver visível na faixa de opções, execute estas etapas para ativar a guia:
    1. Clique no Botão Microsoft Office e, em seguida, clique em Opções do Excel .
    2. Clique na guia popular e, em seguida, clique para selecionar a caixa de seleção Mostrar guia Desenvolvedor na faixa de opções .
    3. Clique em OK .
  3. No grupo de controles na guia Developer , clique em Inserir .
  4. Em controles ActiveX , clique em Mais controles .
  5. Na caixa de diálogo Mais controles , clique em OffCntrDisp .
  6. Desenhe um retângulo na planilha para inserir o controle. resultados O controle será exibida. Logo depois, será exibida uma caixa de mensagem que contém "Documento encontrado em ROT". Em seguida, você verá outra caixa de mensagem semelhante a "documento IDispatch = 0043bf8c." Finalmente, você verá uma caixa de mensagem que informa do nome do documento onde ele foi inserido.

Propriedades

ID do artigo: 190985 - Última revisão: sexta-feira, 30 de março de 2007 - Revisão: 5.1
A informação contida neste artigo aplica-se a:
  • Microsoft Visual C++ 5.0 Enterprise Edition
  • Microsoft Visual C++ 6.0 Enterprise Edition
  • Microsoft Visual C++ 5.0 Professional Edition
  • Microsoft Visual C++ 6.0 Professional Edition
  • Microsoft Visual C++, 32-bit Learning Edition 6.0
  • Microsoft Office Word 2007
  • Microsoft Office Word 2003
  • Microsoft Word 2002 Standard Edition
  • Microsoft Word 2000 Standard Edition
  • Microsoft Word 97 Standard Edition
  • Microsoft Office Excel 2007
  • Microsoft Office Excel 2003
  • Microsoft Excel 2002 Standard Edition
  • Microsoft Excel 2000 Standard Edition
  • Microsoft Excel 97 Standard Edition
Palavras-chave: 
kbmt kbautomation kbhowto KB190985 KbMtpt
Tradução automática
IMPORTANTE: Este artigo foi traduzido por um sistema de tradução automática (também designado por Machine Translation ou MT), não tendo sido portanto traduzido ou revisto por pessoas. A Microsoft possui artigos traduzidos por aplicações (MT) e artigos traduzidos por tradutores profissionais, com o objetivo de oferecer em português a totalidade dos artigos existentes na base de dados de suporte. No entanto, a tradução automática não é sempre perfeita, podendo conter erros de vocabulário, sintaxe ou gramática. A Microsoft não é responsável por incoerências, erros ou prejuízos ocorridos em decorrência da utilização dos artigos MT por parte dos nossos clientes. A Microsoft realiza atualizações freqüentes ao software de tradução automática (MT). Obrigado.
Clique aqui para ver a versão em Inglês deste artigo: 190985

Submeter comentários

 

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