系統裝置枚舉器為我們按類型枚舉已注冊在系統中的fitler提供了統一的方法。而且它能夠區分不同的硬體裝置,即便是同一個filter支援它們。這對那些使用windows驅動模型和ksproxy filter的裝置來說是非常有用的。系統裝置枚舉器對它們按不同的裝置執行個體進行對待(譯注:雖然它們支援相同filter)。
當我們利用系統裝置枚舉器查詢裝置的時候,系統裝置枚舉器為特定類型的裝置(如,音頻捕獲和視訊壓縮)生成了一張枚舉表(enumerator)。類型枚舉器(category enumerator)為每個這種類型的裝置傳回一個moniker,類型枚舉器自動把每一種即插即用的裝置包含在内。
按如下的步驟使用系統裝置枚舉器:
1. 調用方法cocreateinstance生成系統裝置枚舉器。類辨別(clsid)為clsid_systemdeviceenum。
3. 使用ienummoniker::next方法依次得到ienummoniker指針中的每個moniker。該方法傳回一個imoniker接口指針。當next到達枚舉的底部,它的傳回值仍然是s_false,這裡我們仍需要用s_ok來進行檢驗。
4. 想要得到該裝置較為友好的名稱(例如想要在使用者界面中進行顯示),調用imoniker::bindtostorage方法。
5. 如果想要生成并初始化管理該裝置的filter調用3傳回指針的imonitor::bindtoobject方法,接下來調用ifiltergraph::addfilter把該filter添加到視圖中。
下圖說明了上述步驟:
下面的代碼示例了如何枚舉使用者系統中的視訊壓縮器,為了簡化,隻給出了很少的錯誤檢查。
//生成系統裝置枚舉器.
hresult hr;
icreatedevenum *psysdevenum = null;
hr = cocreateinstance(clsid_systemdeviceenum, null, clsctx_inproc_server,
iid_icreatedevenum, (void **)&psysdevenum);
if (failed(hr))
{
return hr;
}
// 獲得視訊壓縮的類枚舉器(class enumerator).
ienummoniker *penumcat = null;
hr = psysdevenum->createclassenumerator(clsid_videocompressorcategory, &penumcat, 0);
if (hr == s_ok)
// 枚舉其中的 moniker.
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))
//如下,得到filter的友好名稱:
variant varname;
variantinit(&varname);
hr = ppropbag->read(l"friendlyname", &varname, 0);
//在你的使用者界面上面顯示.
}
variantclear(&varname);
// 如下,生成該filter的執行個體:
ibasefilter *pfilter;
hr = pmoniker->bindtoobject(null, null, iid_ibasefilter,
(void**)&pfilter);
//将filter加入到graph.
//後面必須記得釋放pfilter.
ppropbag->release();
pmoniker->release();
penumcat->release();
psysdevenum->release();
裝置moniker
lpolestr strname = null;
ibasefilter psrc = null;
hr = pmoniker->getdisplayname(null, null, &strname);
if (succeeded(hr))
// 得到ifiltergraph2的filter graph manager.
ifiltergraph2 *pfg2 = null;
hr = pgraph->queryinterface(iid_ifiltergraph2, (void**)&pfg2);
hr = pfg2->addsourcefilterformoniker(pmoniker, 0, l"source", &psrc);
pfg2->release();
cotaskmemfree(strname);
// 如果成功,記得釋放psrc.
雖然,用上述方法得到的名字也有較好的可讀性,但是我們一般不把它顯示給使用者,如前面所示,我們一般用從ipropertybag得到的名字。
方法imoniker::parsedisplayname和mkparsedisplayname可以用來生成指定filter類型的裝置的moniker。名字以“@device:*:{category-clsid}”,代表了類型的guid,預設的moniker是裝置枚舉器中的第一個moniker。
//視訊捕獲類型
wchar szmon[] = l"@device:*:{860bb310-5d01-11d0-bd3b-00a0c911ce86}";
ibindctx *pbindctx;
hr = createbindctx(0, &pbindctx);
ulong cheaten = 0;
imoniker *pmoniker = 0;
hr = mkparsedisplayname(pbindctx, szmon, &cheaten, &pmoniker);
pbindctx->release();
// 得到名字或綁定至directshow filter.