古人说:知其然亦要知其所以然。其实到了自己来实践这一句话的时候是会感觉此话甚有几分道理的。首先知其然排在前面,是叫我们先学会应用;知其所以然是在知其然的前提下继续往对应模块(如果没有知其然,哪里知道的模块呢)的祖坟上刨,对每个模块的原理进行了解,便对对应模块的灵活应用可扩展。
像我这种人来读这句话的时候就会认为首先就要知其所以然。故而有的时候我把我自己也往往死胡同里面扔,还好从来都没有进过胡同里的垃圾桶,要不然早就被回收了,经过加工之后,我再也找不到曾经的朴实和憨厚,除非重新变成垃圾我才可能来领悟知其然和知其所以然的关系。而且对于下一步来讲,上一步有可能都是知其然。
所以,对于DirectShow视频预览这一块来说,我知道了具体是怎么回事么?我不知道。但是我知道怎么编排代码就能实现视频预览的功能么?是的,我知道,而且我大概已经对这整个流程划分了模块。所以能往每个模块上面刨刨,就刨泡吧。这样就算是第一个层次上面的真正懂了。
DirectShow视频预览中有一步是枚举系统设备,它的步骤为:
平台:VS2010
while(pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK) { //如果枚举到了设备之后 //就对此进行操作,比如将枚举到设备添加到Combo Box 里面呀等等 }
其中pEnumCat是IEnumMoniker类的指针对象。
IEnumMoniker::Next函数原型如下:
HRESULT Next( [in] ULONG celt, [out] IMoniker **rgelt, [in, out] ULONG *pceltFetched );
此函数用来在指定列表中检索指定数目的设备。
如果此函数检测到规定的设备的个数即celt个,则返回S_OK;否则返回S_FALSE
这个过程主要包含获取检索到的设备的设备名、然后通过Combo Box的成员函数将设备名添加到对应列表中。
对应代码
while(pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK) { IPropertyBag *pBag=0; hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag); if(FAILED(hr)) { continue; } if(SUCCEEDED(hr)) { VARIANT var; VariantInit(&var); if(FAILED(hr)) { hr = pBag->Read(L"FriendlyName", &var, NULL); } if(hr == NOERROR) { m_veideoSelect.AddString(var.bstrVal); } } }
当IEnumMoniker::Next获得一个设备名时就将此设备的信息(设备名捕捉到)。
其中pEnumCat是IMoniker类的指针对象。此处用IMoniker::BindToStorage方法的主要目的是返回一个IPropertyBag类的指针,通过此指针访问Read函数可以获得设备的名字。经过VARIANT var和VariantInit(&var)(具体含义可以查看MSDN的,我翻译的效果不会太好)语句后,然后通过pBag->Read(L"FriendlyName", &var, NULL);语句就能将设备名存到var.bstrVal中。
要达到此效果只需要一句:m_veideoSelect.AddString(var.bstrVal);
此次笔记记录完毕。