共用方式為


在沒有介面的情況下優雅降級

因為控件可能不支援除了 IUnknown以外的任何介面,所以容器在遇到任何特定介面時,必須正常降級。

有人可能會質疑控件的實用性,只不過僅僅是 IUnknown。 但請考慮當容器將對象辨識為控件時,控件從容器的視覺程序設計環境 (例如 VB) 接收的優點:

  • 物件的按鈕會出現在工具箱中。
  • 您可以將物件從工具箱拖曳至表單,以建立物件。
  • 您可以為物件提供可視化程式設計環境中可辨識的名稱。
  • 上述的相同名稱可以立即用於撰寫相同窗體上控件的任何其他程式碼(甚至是不同的表單)。
  • 容器可以針對該物件中可用的任何事件,自動提供程式代碼進入點。
  • 容器會針對任何可用的屬性提供自己的屬性流覽 UI。

當對象無法辨識為控件時,它可能會失去所有這些非常強大且有益的整合功能。 例如,在 Visual Basic 4.0 中,很難真正整合一些不是完全意義上控件的隨機物件,但仍可能有屬性和事件。 由於 Visual Basic 4 對控件的想法非常嚴格,因此物件不會取得上述任何整合功能。 但即使是具有 IUnknown的控件,其中控件的存留期會決定某些資源的存在,應該能夠取得上述的整合功能。

由於目前的工具需要一組大型控件介面來取得任何優點,因此控件通常會導致過度實作,因此它們包含的程式代碼比真正需要的還要多。 可能為 7K 的控制元件最終可能是 25K,這在因特網等領域是一個重大的效能問題。 這也導致人們認為,由於實作所有介面的複雜性,人們只能使用像 CDK 這樣的工具來實作控制項,而且當這種控制項需要像 OC30.DLL 這樣的大型 DLL 時,勢必會增加工作集。 如果不需要所有介面,這可讓許多開發人員撰寫非常小且輕量型的控件,並直接使用 OLE 或其他工具,將每個控件的額外負荷降到最低。

這就是為什麼此附錄會將控件辨識為任何具有CLSID和IUnknown介面物件的原因。 即使只有 IUnknown,具有程式設計環境的容器也應該能夠提供至少功能 #3 和 ) 登錄專案,它也會取得 #1 和 #2。 如果物件針對某些事件集提供 IConnectionPointContainer(和 IProvideClassInfo 通常情況下),則可以獲得 #5;如果它支持屬性和方法的 IDispatch,則可以獲得 #6,並在容器中實現更好的程式代碼整合。

簡言之,對象應該能夠至少實作 IDispatch,並透過 IConnectionPointContainer 公開一個事件集,以取得上述所有的視覺功能。

考慮到這一點,下表描述容器在沒有任何可能介面的情況下可能執行的動作。 請注意,只有那些介面會被列出,容器會直接透過 QueryInterface取得。 其他介面,例如 IOleInPlaceActiveObject,是透過其他方式取得。

介面 介面不存在的意義
IViewObject2
由於控件沒有自繪視覺效果,因此無法提供明確的界限或尺寸。 在執行時,如果這個介面不存在,容器不會嘗試繪製任何內容。 在設計時間中,容器至少必須針對這類控件繪製某種名稱的預設矩形,因此可視化程式設計環境中的使用者可以選取物件,並查看其存在的屬性、方法和事件。 處理沒有 IViewObject2 對於良好的視覺程式設計支持至關重要。
IOleObject
控件不需要任何站點,也不參與任何內嵌物件的佈局協商。 容器可能預期來自此介面的任何資訊(例如控制範圍)都應該填入容器提供的預設值。
IOleInPlaceObject
控件不會進入就地啟動狀態(如同標籤),因此不會嘗試以這種方式啟用。 其唯一可能被啟用的地方是其屬性頁。
IOleControl
控件沒有助記鍵,也不會使用環境屬性,而且不會在意容器是否忽略事件。 如果沒有這個介面,容器就不會呼叫其方法。
IDataObject
控件不會提供任何屬性集,也不會提供任何可快取的視覺轉譯,因此容器會選擇在此介面缺席的情況下快取某些默認簡報(特別是支援CF_METAFILEPICT),並停用任何屬性集相關功能。
IDispatch
控件沒有自定義屬性或方法。 容器在此情況下不需要顯示任何控制屬性,並應禁止任何容器無法辨識且不屬於其擴展控件的自定義方法呼叫(這些控件可能支援方法和屬性)。 由於擴充控件通常會將特定的 IDispatch 呼叫委派給控件,因此延伸控件不應預期控件有 IDispatch 的能力。
IConnectionPointContainer
控件沒有事件,因此容器不需要考慮處理任何事件。
IProvideClassInfo
IProvideClassInfo2
控件沒有類型資訊或事件,或容器必須透過控件的登錄專案進入控件的類型資訊。 這個介面的存在是優化。
指定屬性頁面
控件沒有屬性頁,因此如果容器有任何UI會叫用它們,容器應該停用該UI。
IPerPropertyBrowsing
控件本身沒有顯示名稱、沒有預先決定的字串和值,也沒有頁面對應的屬性。 此介面幾乎一律用於產生容器使用者介面,因此如果沒有此介面,就會停用這類UI元素。
IPersist*
控件沒有可說的持續性狀態,因此容器不需要擔心儲存任何控件特定的數據。 當然,容器會在其自己的窗體或文件中儲存控件的相關信息,但控件本身對那些信息沒有任何貢獻。
IOleCache
IOleCache2
物件不支援快取功能。 容器仍然可以透過自行使用 CreateDataCache 來建立資料快取,從而支援快取

容器