使用系統裝置列舉值

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

系統裝置列舉值提供統一的方式,依類別列舉使用者系統上註冊的篩選。 此外,它也會區分個別的硬體裝置,即使相同的篩選支援它們也一樣。 這特別適用于使用 Windows 驅動程式模型 (WDM) 和 KSProxy 篩選的裝置。 例如,使用者可能有數個 WDM 視訊擷取裝置,全都由相同篩選準則支援。 系統裝置列舉值會將它們視為個別的裝置實例。

系統裝置列舉值的運作方式是建立特定類別的列舉值,例如音訊擷取或視訊壓縮。 類別列舉值會針對類別中的每個裝置傳回唯一的 Moniker。 類別列舉值會自動在類別中包含任何相關的隨插即用裝置。 如需類別清單,請參閱 篩選類別

若要使用系統裝置列舉值,請執行下列動作:

  1. 呼叫 CoCreateInstance來建立系統裝置列舉值。 (CLSID) 類別識別碼是CLSID_SystemDeviceEnum。
  2. 使用所需類別的 CLSID 呼叫 ICreateDevEnum::CreateClassEnumerator 來取得類別列舉值。 這個方法會傳回 IEnumMoniker 介面指標。 如果類別是空的 (或不存在) ,則方法會傳回S_FALSE而不是錯誤碼。 如果是,傳回的 IEnumMoniker 指標為 Null ,並取消參考它會導致例外狀況。 因此,當您呼叫 CreateClassEnumerator時明確測試S_OK,而不是呼叫一般的 SUCCEEDED 宏。
  3. 使用 IEnumMoniker::Next 方法來列舉每個 Moniker。 這個方法會傳回 IMoniker 介面指標。 當 Next 方法到達列舉的結尾時,也會傳回S_FALSE,因此再次檢查S_OK。
  4. 例如,若要擷取裝置 (易記名稱,若要在使用者介面) 中顯示,請呼叫 IMoniker::BindToStorage 方法。
  5. 若要建立並初始化管理裝置的 DirectShow 篩選,請在 Moniker 上呼叫 IMoniker::BindToObject 。 呼叫 IFilterGraph::AddFilter 以將篩選新增至圖形。

下圖說明此程序。

列舉裝置

下列範例示範如何列舉安裝在使用者系統上的影片壓縮套件。 為了簡潔起見,此範例會執行最少的錯誤檢查。

// Create the System Device Enumerator.
HRESULT hr;
ICreateDevEnum *pSysDevEnum = NULL;
hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
    IID_ICreateDevEnum, (void **)&pSysDevEnum);
if (FAILED(hr))
{
    return hr;
}

// Obtain a class enumerator for the video compressor category.
IEnumMoniker *pEnumCat = NULL;
hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoCompressorCategory, &pEnumCat, 0);

if (hr == S_OK) 
{
    // Enumerate the monikers.
    IMoniker *pMoniker = NULL;
    ULONG cFetched;
    while(pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)
    {
        IPropertyBag *pPropBag;
        hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, 
            (void **)&pPropBag);
        if (SUCCEEDED(hr))
        {
            // To retrieve the filter's friendly name, do the following:
            VARIANT varName;
            VariantInit(&varName);
            hr = pPropBag->Read(L"FriendlyName", &varName, 0);
            if (SUCCEEDED(hr))
            {
                // Display the name in your UI somehow.
            }
            VariantClear(&varName);

            // To create an instance of the filter, do the following:
            IBaseFilter *pFilter;
            hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter,
                (void**)&pFilter);
            // Now add the filter to the graph. 
            //Remember to release pFilter later.
            pPropBag->Release();
        }
        pMoniker->Release();
    }
    pEnumCat->Release();
}
pSysDevEnum->Release();

裝置 Monikers

針對裝置 Monikers,您可以將 Moniker 傳遞至 IFilterGraph2::AddSourceFilterForMoniker 方法,以建立裝置的擷取篩選。 如需範例程式碼,請參閱該方法的檔。

IMoniker::GetDisplayName方法會傳回 Moniker 的顯示名稱。 雖然顯示名稱是可讀取的,但您通常不會將它顯示給使用者。 請改用屬性包中的易記名稱,如先前所述。

IMoniker::P arseDisplayName方法或MkParseDisplayName函式可用來為指定的篩選類別建立預設裝置 Moniker。 使用具有 格式 @device:*:{category-clsid} 的顯示名稱,其中 category-clsid 是類別 GUID 的字串表示。 預設 Moniker 是該類別的裝置列舉值所傳回的第一個 Moniker。