共用方式為


使用 CUnknown

[與此頁面 相關的功能 DirectShow是舊版功能。 它已被 MediaPlayerIMFMediaEngineMedia Foundation 中的音訊/視訊擷取取代。 這些功能已針對Windows 10和Windows 11進行優化。 Microsoft 強烈建議新程式碼盡可能使用 MediaPlayerIMFMediaEngine音訊/視訊擷取 ,而不是 DirectShow。 Microsoft 建議盡可能重寫使用舊版 API 的現有程式碼,以使用新的 API。]

DirectShow 會在名為CUnknown的基類中實作IUnknown。 您可以使用 CUnknown 衍生其他類別,只覆寫跨元件變更的方法。 DirectShow 中大部分的其他基類都衍生自 CUnknown,因此您的元件可以直接繼承自 CUnknown 或另一個基類。

INonDelegatingUnknown

CUnknown 會實作 INonDelegatingUnknown。 它會在內部管理參考計數,而且在大部分情況下,衍生類別可以繼承兩個沒有變更的參考計數方法。 請注意,當參考計數下降為零時 ,CUnknown 會自行刪除。 另一方面,您必須覆寫 CUnknown::NonDelegatingQueryInterface,因為基類中的 方法會在收到IID_IUnknown以外的任何 IID 時傳回E_NOINTERFACE。 在您的衍生類別中,測試您支援的介面 IID,如下列範例所示:

STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv)
{
    if (riid == IID_ISomeInterface)
    {
        return GetInterface((ISomeInterface*)this, ppv);
    }
    // Default: Call parent class method. 
    // The CUnknown class must be in the inheritance chain.
    return CParentClass::NonDelegatingQueryInterface(riid, ppv);
}

公用程式函式 GetInterface (請參閱 COM 協助程式函 式) 設定指標、以安全線程方式遞增參考計數,並傳回S_OK。 在預設案例中,呼叫基類方法並傳回結果。 如果您衍生自另一個基類,請改為呼叫其 NonDelegatingQueryInterface 方法。 這可讓您支援父類別支援的所有介面。

IUnknown

如先前所述,每個元件的委派 IUnknown 版本都相同,因為它不會再叫用正確的非委派版本實例。 為了方便起見,標頭檔 Combase.h 包含宏 DECLARE_IUNKNOWN,它會將三個委派方法宣告為內嵌方法。 它會展開至下列程式碼:

STDMETHODIMP QueryInterface(REFIID riid, void **ppv) {      
    return GetOwner()->QueryInterface(riid,ppv);            
};                                                          
STDMETHODIMP_(ULONG) AddRef() {                             
    return GetOwner()->AddRef();                            
};                                                          
STDMETHODIMP_(ULONG) Release() {                            
    return GetOwner()->Release();                           
};

公用程式函式 CUnknown::GetOwner 會擷取擁有此元件之元件的 IUnknown 介面指標。 針對匯總的元件,擁有者是外部元件。 否則,元件會自行擁有。 將DECLARE_IUNKNOWN宏包含在類別定義的 public 區段中。

類別建構函式

您的類別建構函式應該叫用父類別的建構函式方法,除了它對類別執行的任何動作之外。 下列範例是典型的建構函式方法:

CMyComponent(TCHAR *tszName, LPUNKNOWN pUnk, HRESULT *phr) 
    : CUnknown(tszName, pUnk, phr)
{ 
    /* Other initializations */ 
};

方法會採用下列參數,它會直接傳遞至 CUnknown 建構函式方法。

  • tszName 會指定元件的名稱。
  • pUnk 是匯總 IUnknown的指標。
  • pHr 是 HRESULT 值的指標,表示方法的成功或失敗。

總結

下列範例顯示支援 IUnknown 的衍生類別,以及名為 ISomeInterface 的假設介面:

class CMyComponent : public CUnknown, public ISomeInterface
{
public:

    DECLARE_IUNKNOWN;

    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv)
    {
        if( riid == IID_ISomeInterface )
        {
            return GetInterface((ISomeInterface*)this, ppv);
        }
        return CUnknown::NonDelegatingQueryInterface(riid, ppv);
    }

    CMyComponent(TCHAR *tszName, LPUNKNOWN pUnk, HRESULT *phr) 
        : CUnknown(tszName, pUnk, phr)
    { 
        /* Other initializations */ 
    };

    // More declarations will be added later.
};

此範例說明下列幾點:

撰寫篩選的下一個步驟是讓應用程式建立元件的新實例。 這需要瞭解 DLL 及其與類別處理站和類別建構函式方法的關聯性。 如需詳細資訊,請參閱 如何建立 DirectShow 篩選 DLL

如何實作 IUnknown