使用系統裝置列舉值
[與此頁面相關的功能 DirectShow是舊版功能。 它已被 MediaPlayer、 IMFMediaEngine和 Media Foundation 中的音訊/視訊擷取取代。 這些功能已針對Windows 10和Windows 11進行優化。 Microsoft 強烈建議新程式碼盡可能使用 MediaPlayer、 IMFMediaEngine 和 音訊/視訊擷取 ,而不是 DirectShow。 Microsoft 建議使用舊版 API 的現有程式碼盡可能重寫為使用新的 API。
系統裝置列舉值提供統一的方式,依類別列舉使用者系統上註冊的篩選。 此外,它也會區分個別的硬體裝置,即使相同的篩選支援它們也一樣。 這特別適用于使用 Windows 驅動程式模型 (WDM) 和 KSProxy 篩選的裝置。 例如,使用者可能有數個 WDM 視訊擷取裝置,全都由相同篩選準則支援。 系統裝置列舉值會將它們視為個別的裝置實例。
系統裝置列舉值的運作方式是建立特定類別的列舉值,例如音訊擷取或視訊壓縮。 類別列舉值會針對類別中的每個裝置傳回唯一的 Moniker。 類別列舉值會自動在類別中包含任何相關的隨插即用裝置。 如需類別清單,請參閱 篩選類別。
若要使用系統裝置列舉值,請執行下列動作:
- 呼叫 CoCreateInstance來建立系統裝置列舉值。 (CLSID) 類別識別碼是CLSID_SystemDeviceEnum。
- 使用所需類別的 CLSID 呼叫 ICreateDevEnum::CreateClassEnumerator 來取得類別列舉值。 這個方法會傳回 IEnumMoniker 介面指標。 如果類別是空的 (或不存在) ,則方法會傳回S_FALSE而不是錯誤碼。 如果是,傳回的 IEnumMoniker 指標為 Null ,並取消參考它會導致例外狀況。 因此,當您呼叫 CreateClassEnumerator時明確測試S_OK,而不是呼叫一般的 SUCCEEDED 宏。
- 使用 IEnumMoniker::Next 方法來列舉每個 Moniker。 這個方法會傳回 IMoniker 介面指標。 當 Next 方法到達列舉的結尾時,也會傳回S_FALSE,因此再次檢查S_OK。
- 例如,若要擷取裝置 (易記名稱,若要在使用者介面) 中顯示,請呼叫 IMoniker::BindToStorage 方法。
- 若要建立並初始化管理裝置的 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。