标签:style http color io os ar 使用 for strong
本篇文档我们将要讲述如何给一个filter创建一个属性页,通过CBasePropertyPage基类。这篇文档的实例代码演 示了创建属性页的步骤,这里我们假设我们要创建属性页的视频filter支持饱和度属性页,这个属性页有一个滑动条,用户可以通过这个滑动条来控制饱和 度。
第一步,设置属性的机理
Filter必须支持一种和属性页沟通的方式,通过属性页可以设置或者获取filter的属性,下面是可能的三种方式
1暴露一个接口
2通过IDispatch支持自动化属性
3暴露IPropertyBag 接口,并定义一系列的属性
下面的例子利用了一个普通的COM接口,叫做ISaturaton,这并不是一个真正的com接口,只是我们用来在这里举例的,你也可以自己定义任何的com对象。
首先我们在一个头文件中声明接口的ID和定义。
// Always create new GUIDs! Never copy a GUID from an example.
DEFINE_GUID(IID_ISaturation, 0x19412d6e, 0x6401,
0x475c, 0xb0, 0x48, 0x7a, 0xd2, 0x96, 0xe1, 0x6a, 0x19);
interface ISaturation : public IUnknown
{
STDMETHOD(GetSaturation)(long *plSat) = 0;
STDMETHOD(SetSaturation)(long lSat) = 0;
};
你也可以用IDL定义接口,并用MIDL编译器创建头文件,然后在Filter上实现这个接口,这个例子采用“Get”,“Set”方法来设置饱和度的值,注意,修改这个m_lSaturation的值的时候一定要进行保护class CGrayFilter : public ISaturation,
{
private:
CCritSec m_csShared; // Protects shared data.
long m_lSaturation; // Saturation level.
public:
STDMETHODIMP GetSaturation(long *plSat)
{
if (!plSat) return E_POINTER;
CAutoLock lock(&m_csShared);
*plSat = m_lSaturation;
return S_OK;
}
STDMETHODIMP SetSaturation(long lSat)
{
CAutoLock lock(&m_csShared);
if (lSat < SATURATION_MIN || lSat > SATURATION_MAX)
{
return E_INVALIDARG;
}
m_lSaturation = lSat;
return S_OK;
}
};
当然你实现接口的一些细节可能和上面的代码不一致。反正你自己实现就是了// Always create new GUIDs! Never copy a GUID from an example. DEFINE_GUID(CLSID_SaturationProp, 0xa9bd4eb, 0xded5, 0x4df0, 0xba, 0xf6, 0x2c, 0xea, 0x23, 0xf5, 0x72, 0x61);然后要实现ISpecifyPropertyPages接口的GetPages方法:
class CGrayFilter : public ISaturation,
public ISpecifyPropertyPages,
{
public:
STDMETHODIMP GetPages(CAUUID *pPages)
{
if (pPages == NULL) return E_POINTER;
pPages->cElems = 1;
pPages->pElems = (GUID*)CoTaskMemAlloc(sizeof(GUID));
if (pPages->pElems == NULL)
{
return E_OUTOFMEMORY;
}
pPages->pElems[0] = CLSID_SaturationProp;
return S_OK;
}
};
}第三步,支持QueryInterface
为了暴露Filter的接口,照着下面的步骤作哦
1 在你的filter中包含DECLARE_IUNKNOWN宏的声明: Public: DECLARE_IUNKNOWN; 2 重载CUnknown::NonDelegatingQueryInterf第四步,创建属性页ace 方法来检查两个接口的IIDs。 STDMETHODIMP CGrayFilter::NonDelegatingQueryInterf ace(REFIID riid, void **ppv) { if (riid == IID_ISpecifyPropertyPages) { return GetInterface(static_cast<ISpecifyPropertyPages*>(this), ppv); } if (riid == IID_ISaturation) { return GetInterface(static_cast<IYuvGray*>(this), ppv); } return CBaseFilter::NonDelegatingQueryInterf ace(riid, ppv); }
class CGrayProp : public CBasePropertyPage
{
private:
ISaturation *m_pGray; // Pointer to the filter‘s custom interface.
long m_lVal // Store the old value, so we can revert.
long m_lNewVal; // New value.
public:
};
看看构造函数吧CGrayProp::CGrayProp(IUnknown *pUnk) :
CBasePropertyPage(NAME("GrayProp"), pUnk, IDD_PROPPAGE, IDS_PROPPAGE_TITLE),
m_pGray(0)
{ }
下面,你还要记得重载CBasePropertyPage 的几个方法哦第五步,保存filter的一个指针
通过重载CBasePropertyPage::OnConnect方法将一个指针保存到filter,下面的例子演示了如何通过方法传递过来的参数查询filter支持的接口
HRESULT CGrayProp::OnConnect(IUnknown *pUnk)
{
if (pUnk == NULL)
{
return E_POINTER;
}
ASSERT(m_pGray == NULL);
return pUnk->QueryInterface(IID_ISaturation,
reinterpret_cast<void**>(&m_pGray));
}第六步,初始化对话框
通过重载CBasePropertyPage::OnActivate方法来初始化一个对话框,在这个例子里,属性页使用了滑动条,所以,在初始化的第一步就是要初始化控件动态库,然后再初始化slider。
HRESULT CGrayProp::OnActivate(void)
{
INITCOMMONCONTROLSEX icc;
icc.dwSize = sizeof(INITCOMMONCONTROLSEX);
icc.dwICC = ICC_BAR_CLASSES;
if (InitCommonControlsEx(&icc) == FALSE)
{
return E_FAIL;
}
ASSERT(m_pGray != NULL);
HRESULT hr = m_pGray->GetSaturation(&m_lVal);
if (SUCCEEDED(hr))
{
SendDlgItemMessage(m_Dlg, IDC_SLIDER1, TBM_SETRANGE, 0,
MAKELONG(SATURATION_MIN, SATURATION_MAX));
SendDlgItemMessage(m_Dlg, IDC_SLIDER1, TBM_SETTICFREQ,
(SATURATION_MAX - SATURATION_MIN) / 10, 0);
SendDlgItemMessage(m_Dlg, IDC_SLIDER1, TBM_SETPOS, 1, m_lVal);
}
return hr;
}
第七步,处理窗口消息private:
void SetDirty()
{
m_bDirty = TRUE;
if (m_pPageSite)
{
m_pPageSite->OnStatusChange(PROPPAGESTATUS_DIRTY);
}
}
当用户改变了属性的时候,在OnReceiveMessage方法中调用上面的函数。BOOL CGrayProp::OnReceiveMessage(HWND hwnd,
UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_COMMAND:
if (LOWORD(wParam) == IDC_DEFAULT)
{
// User clicked the ‘Revert to Default‘ button.
m_lNewVal = SATURATION_DEFAULT;
m_pGray->SetSaturation(m_lNewVal);
// Update the slider control.
SendDlgItemMessage(m_Dlg, IDC_SLIDER1, TBM_SETPOS, 1,
m_lNewVal);
SetDirty();
return (LRESULT) 1;
}
break;
case WM_HSCROLL:
{
// User moved the slider.
switch(LOWORD(wParam))
{
case TB_PAGEDOWN:
case SB_THUMBTRACK:
case TB_PAGEUP:
m_lNewVal = SendDlgItemMessage(m_Dlg, IDC_SLIDER1,
TBM_GETPOS, 0, 0);
m_pGray->SetSaturation(m_lNewVal);
SetDirty();
}
return (LRESULT) 1;
}
} // Switch.
// Let the parent class handle the message.
return CBasePropertyPage::OnReceiveMessage(hwnd,uMsg,wParam,lParam);
}第八步,处理属性的改变
重载CBasePropertyPage::OnApplyChanges方法来提交属性页的改变,如果用户单击了确定,或者应用按钮,OnApplyChanges方法都会调用到
HRESULT CGrayProp::OnApplyChanges(void)
{
m_lVal = m_lNewVal;
return S_OK;
}第九步,断开属性页连接
重载 CBasePropertyPage::OnDisconnect方法来释放你在OnConnect方法中请求的所有的接口,如果用户没有更新属性,而是 单击了取消按钮,你还要将属性的原始值保存下来。当用户单击取消按钮,但是没有相应的响应这个消息的方法,所以,你要检查用户是否调用了 OnApplyChanges方法,看看例子也好:
HRESULT CGrayProp::OnDisconnect(void)
{
if (m_pGray)
{
// If the user clicked OK, m_lVal holds the new value.
// Otherwise, if the user clicked Cancel, m_lVal is the old value.
m_pGray->SetSaturation(m_lVal);
m_pGray->Release();
m_pGray = NULL;
}
return S_OK;
}第十步,支持com的注册
最后一步就是要支持com的注册,因此 属性框才能够创建你属性页的实例,首先在全局数组g_Templates添加一个类厂模板的说明。这个全局的数组是你的DLL中创建的所有的com对象都要用到的。
const AMOVIESETUP_FILTER FilterSetupData =
{
};
CFactoryTemplate g_Templates[] =
{
// This entry is for the filter.
{
wszName,
&CLSID_GrayFilter,
CGrayFilter::CreateInstance,
NULL,
&FilterSetupData
},
// This entry is for the property page.
{
L"Saturation Props",
&CLSID_SaturationProp,
CGrayProp::CreateInstance,
NULL, NULL
}
};
如果你用下面的方式声明全局数组,数组的大小就会自动地得到修改static CUnknown * WINAPI CreateInstance(LPUNKNOWN pUnk, HRESULT *pHr)
{
CGrayProp *pNewObject = new CGrayProp(pUnk);
if (pNewObject == NULL)
{
*pHr = E_OUTOFMEMORY;
}
return pNewObject;
}
如果想测试属性页,可以注册DLL,然后将filter加载到GraphEdit,鼠标右击来查看filter的属性。
采集参数的设置采集前需要对要采集的视频格式、图像质量进行设置,如视频的分辨率、帧率和数据格式,图像的亮度、色度和饱和度参数设置等。下面分别对这两种设置进行讲述。
1.视频格式设置
对采集设备的参数进行配置,首先确定设备的类型:VFW、WDM驱动模型。目前流行的采集设备大部分采用WDM模式,采集设备在 DirectShow中被当做一个滤波器组件,所以配置采集设备就是对该滤波器的引脚进行设置。在确保滤波器链表完全建立前,可以使用如下的过程配置视频 格式。
void CCaptureClass::ConfigCameraPin(HWND hwndParent)
{
HRESULT hr; |
|
| (点击查看大图)图9-1 |
2.图像参数设置
图像参数设置类似于视频格式配置,根据设备的驱动类型VFW、WDM使用不同的技术配置设备的参数,这里我们同样假定采集设备的类型为WDM,配置过程如下。
void CCaptureClass::ConfigCameraFilter(HWND hwndParent)
{
HRESULT hr=0;
ISpecifyPropertyPages *pProp;
hr = m_pBF->QueryInterface(IID_ISpecifyPropertyPages, (void **)&pProp);
if (SUCCEEDED(hr))
{
//获取滤波器名称和IUnknown接口指针
FILTER_INFO FilterInfo;
hr = m_pBF->QueryFilterInfo(&FilterInfo);
IUnknown *pFilterUnk;
m_pBF->QueryInterface(IID_IUnknown, (void **)&pFilterUnk);
//显示该页
CAUUID caGUID;
pProp->GetPages(&caGUID);
OleCreatePropertyFrame(
hwndParent, |
|
| (点击查看大图)图9-2 |
标签:style http color io os ar 使用 for strong
原文地址:http://blog.csdn.net/mao0514/article/details/40188523