如何创建Filter的属性页[1]

[入库:2005年8月19日] [更新:2007年3月24日]

本文简介:选择自 aoosang 的 blog

摘要:


本篇文档我们将要讲述如何给一个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, /* other inherited classes. */
{
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;
}
};
当然你实现接口的一些细节可能和上面的代码不一致。反正你自己实现就是了

第二步,实现ispecifypropertypages接口

做完了上一步,下面就要在你个filter中实现ispecifypropertypages接口,这个接口只有一个方法,getpages,这个方法返回filter所支持的所有的属性页的clsid。在这个例子里,filter只支持一个属性页,
首先产生一个clsid,并在头文件声明
// 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,
/* other inherited classes. */
{
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::nondelegatingqueryinterface 方法来检查两个接口的iids。
stdmethodimp cgrayfilter::nondelegatingqueryinterface(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::nondelegatingqueryinterface(riid, ppv);
}
第四步,创建属性页
到这一步,filter已经支持一个属性页的所需要的东西了,下一步就是要实现属性页本身了。
首先创建一个对话框的资源,然后以这个对话的资源声明一个类,要从cbasepropertypage. 派生,

图1
下面的代码显示了部分的声明,包含了我们在后面将要用到的部分变量。
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 的几个方法哦
onconnect,当属性页创建的时候,会调用这个方法,通过这个方法将iunknown指针付给filter。
onactivate 当对话框创建的时候被调用
onreceivemessage 当对话框接收到窗口消息时被调用
onapplychanges当用户单击ok或者apply 按钮来确认对属性进行更新时,调用
ondisconnect 当用户取消property sheet时调用

第五步,保存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));
}

本文关键:如何创建Filter的属性页
 

本站最佳浏览方式为 分辨率 1024x768 IE 6.0(或更高版本的 IE浏览器)

go top