您目前已離線,請等候您的網際網路重新連線

如何從一個 OCX 取得 IDispatch Excel 或 Word 文件

重要:本文是以 Microsoft 機器翻譯軟體翻譯而成,而非使用人工翻譯而成。Microsoft 同時提供使用者人工翻譯及機器翻譯兩個版本的文章,讓使用者可以依其使用語言使用知識庫中的所有文章。但是,機器翻譯的文章可能不盡完美。這些文章中也可能出現拼字、語意或文法上的錯誤,就像外國人在使用本國語言時可能發生的錯誤。Microsoft 不為內容的翻譯錯誤或客戶對該內容的使用所產生的任何錯誤或損害負責。Microsoft也同時將不斷地就機器翻譯軟體進行更新。

190985
結論
它是很常見的 OLE 控制項需要其容器 IDispatch。您通常可以從伺服器如 IOleClientSite 上的立即存取介面使用 QueryInterface() 來取得 [IDispatch。不過,某些伺服器如 Microsoft Excel 的這種方法失敗。

若要取得 [IDispatch 另一個方法是藉由使用 GetActiveObject() API 來取得伺服器的 IDispatch 從 ROT。不過,此方法需要您必須能夠取得 CLSID 或伺服器的程式識別碼。此外,模稜兩可的情況下會發生您無法區別伺服器的多個執行個體之間。

這份文件會使用另一種方法,取得適用於 Microsoft Excel 和 Microsoft Word,即使執行多個執行個體的 IDispatch。

下列步驟可讓您建置可取得容器的文件物件 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();					
    這會新增至與自訂 MyOleObject IOleObject COleControl 的預設實作會覆寫。

  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);      }					
    這是您的實作大多是委派給所有的 SetHostNames() 以外的預設 COleControl IOleObject 實作其呼叫的 IOleObject。您補漏白 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. 按一下 [開發 o 人 h 員 û 工 u 具 ã] 索引標籤。 如果您看在功能區上不見 [開發 o 人 h 員 û 工 u 具 ã] 索引標籤請依照下列步驟執行以啟用 [] 索引標籤:
    1. 按一下 Microsoft Office 按鈕,然後按一下 [Excel 選項
    2. 按一下 [常用] 索引標籤,然後按一下以選取 [在功能區顯示開發 o 人 h 員 û 工 u 具 ã 定位點] 核取方塊。
    3. 按一下 [確定]
  3. 在 [開發 o 人 h 員 û 工 u 具 ã] 索引標籤上的 [控制項] 群組按一下 [插入]。
  4. 在 [ActiveX 控制項,] 之下按一下 [其他控制項]。
  5. 在 [其他控制項] 對話方塊中,按一下 OffCntrDisp
  6. 在工作表插入控制項中繪製一個矩形。結果控制項將會出現。不久之後包含 ROT 中的發現文件 」 的訊息方塊隨即出現。接下來,您應該會看到另一個訊息方塊類似的 「 文件 IDispatch = 0043bf8c"最後,您應該看到訊息方塊,通知您文件插入位置的名稱。
getobject XL2007

警告:本文已自動翻譯

內容

文章識別碼:190985 - 最後檢閱時間:03/30/2007 17:27:45 - 修訂: 5.1

  • 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
  • kbmt kbautomation kbhowto KB190985 KbMtzh
意見反應