使用系統裝置列舉器
[與此頁面相關聯的功能,DirectShow是舊版功能。 它已被 MediaPlayer、IMFMediaEngine,以及媒體基金會中的 音訊/視訊擷取取代。 這些功能已針對 Windows 10 和 Windows 11 進行優化。 Microsoft強烈建議新程式代碼盡可能在媒體 基礎中使用 MediaPlayer、IMFMediaEngine 和 音訊/視訊擷取,而不是 DirectShow。 Microsoft建議使用舊版 API 的現有程式代碼,盡可能改寫成使用新的 API。]
系統裝置列舉值提供統一的方式,依類別列舉用戶系統上註冊的篩選。 此外,它也會區分個別硬體裝置,即使相同的篩選器支援它們也一樣。 這特別適用於使用 Windows 驅動程式模型 (WDM) 和 KSProxy 篩選器的裝置。 例如,使用者可能有數個 WDM 視訊擷取裝置,全部都由相同的篩選所支援。 系統裝置列舉器會將它們視為個別的裝置個體。
系統裝置列舉值的運作方式是針對特定類別建立列舉值,例如音訊擷取或視訊壓縮。 類別列舉值會針對類別中的每個裝置傳回唯一的名稱。 類別列舉器會自動在類別中,包含任何相關的隨插即用裝置。 如需類別清單,請參閱 篩選類別。
若要使用系統裝置列舉程式,請執行下列動作:
- 呼叫 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();
裝置名稱
針對裝置識別名,您可以將識別名傳遞給 IFilterGraph2::AddSourceFilterForMoniker 方法,以為裝置建立擷取篩選器。 如需範例程式代碼,請參閱該方法的檔。
IMoniker::GetDisplayName 方法會傳回 Moniker 的顯示名稱。 雖然顯示名稱是可讀取的,但您通常不會將它顯示給使用者。 改為從屬性包中取得友善名稱,如前所述。
IMoniker::ParseDisplayName 方法或 MkParseDisplayName 函式可用來建立指定篩選類別的預設裝置識別名稱。 使用格式為 @device:*:{category-clsid}
的顯示名稱,其中 category-clsid
是類別 GUID 的字串表示。 默認命名是由該類別的設備枚舉器傳回的第一個命名。