天天看點

如何使用系統裝置枚舉器

系統裝置枚舉器為我們按類型枚舉已注冊在系統中的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.

繼續閱讀