共用方式為


使用系統裝置列舉器

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

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

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

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

  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();

裝置名稱

針對裝置識別名,您可以將識別名傳遞給 IFilterGraph2::AddSourceFilterForMoniker 方法,以為裝置建立擷取篩選器。 如需範例程式代碼,請參閱該方法的檔。

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

IMoniker::ParseDisplayName 方法或 MkParseDisplayName 函式可用來建立指定篩選類別的預設裝置識別名稱。 使用格式為 @device:*:{category-clsid}的顯示名稱,其中 category-clsid 是類別 GUID 的字串表示。 默認命名是由該類別的設備枚舉器傳回的第一個命名。