GraphEdit を使うとフィルタ独自のプロパティページを表示することができる。ここで作ったフィルタ にプロパティページを追加して GraphEdit から表示できるようにしてみよう。
プロパティページの準備
プロパティページはCBasePropertyPage
を派生した COM クラスとして定義する。GUID を定義し、regsvr32 で登録できるようにする必要がある。ここではプロパティページのクラスをCMySourceExProp
として定義する。
まずCMySourceExProp
のクラスIDを定義する。
1 2 3 | // {3248D86E-4450-4f2b-AD43-5D8DDCFBABB6}
DEFINE_GUID(CLSID_MySourceExProp,
0x3248d86e, 0x4450, 0x4f2b, 0xad, 0x43, 0x5d, 0x8d, 0xdc, 0xfb, 0xab, 0xb6);
|
CMySourceExProp
を regsvr32 で登録するために g_Templates
を拡張する。
1 2 3 4 | CFactoryTemplate g_Templates [] = {
{ TEMPLATE_NAME, &CLSID_MySourceEx, CMySourceEx::CreateInstance, NULL, &afFilterInfo },
{ PROP_TEMPLATE_NAME, &CLSID_MySourceExProp, CMySourceExProp::CreateInstance, NULL, NULL}
};
|
IDD_PROP
というリソース ID でプロパティページのリソースを作成する。
IDS_PROP_TITLE
というリソース ID で文字列リソースを作成する。プロパティページのタブに表示される文字列として使われる。
ソースフィルタクラスの拡張
ソースフィルタクラスCMySourceEx
にcode>ISpecifyPropertyPagesインターフェイスを実装する。
NonDelegatingQueryInterface`も問い合わせに対応できるように修正しよう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | class CMySourceEx : CSource, public IColor, public ISpecifyPropertyPages {
public:
DECLARE_IUNKNOWN
CMySourceEx(LPUNKNOWN pUnk,HRESULT *phr);
~CMySourceEx();
static CUnknown * WINAPI CreateInstance(LPUNKNOWN pUnk, HRESULT *phr);
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
//IColor
STDMETHODIMP SetColor(DWORD color);
STDMETHODIMP GetColor(DWORD *pColor);
//ISpecifyPropertyPages
STDMETHODIMP GetPages(CAUUID *pPages);
protected:
private:
DWORD m_Color;
};
|
1 2 3 4 5 6 | STDMETHODIMP CMySourceEx::NonDelegatingQueryInterface(REFIID riid, void **ppv) {
if (riid==IID_ISpecifyPropertyPages) {
return GetInterface((ISpecifyPropertyPages*)this, ppv);
}
return CSource::NonDelegatingQueryInterface(riid, ppv);
}
|
GetPages
ではプロパティページのクラスIDを引数のpPages
に設定する。CoTaskMemAlloc
でクラスIDを格納するメモリを動的確保すること。
1 2 3 4 5 6 7 8 | STDMETHODIMP CMySourceEx::GetPages(CAUUID *pPages) {
CheckPointer(pPages, E_POINTER);
pPages->cElems=1;
pPages->pElems=(GUID*)CoTaskMemAlloc(sizeof(GUID));
CheckPointer(pPages->pElems, E_OUTOFMEMORY);
pPages->pElems[0]=CLSID_MySourceExProp;
return S_OK;
}
|
プロパティクラスの実装
プロパティクラスは DirectShow 基底クラスにある CBasePropertyPage
クラスを派生させて作成する。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class CMySourceExProp : CBasePropertyPage
{
public:
CMySourceExProp(IUnknown *pUnknown);
static CUnknown * WINAPI CreateInstance(IUnknown *pUnk, HRESULT *phr);
HRESULT OnConnect(IUnknown *pUnknown);
HRESULT OnActivate(void);
BOOL OnReceiveMessage(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
HRESULT OnApplyChanges(void);
HRESULT OnDisconnect(void);
private:
IColor *m_pColor;
DWORD m_CurrVal;
DWORD m_NewVal;
};
|
m_CurrVal
と m_NewVal
に注目してほしい。プロパティページを開くと、OK, Apply, Cancel の 3 つのボタンが存在する。ユーザがスライダーを動かして明るさを変更したあと、Cancel ボタンを押下したとき、以前の明るさに戻してプロパティページが閉じられるのが自然であろう。従って「新しく設定する値(m_NewVal)」と「現在の値(m_CurrVal)」を保持しておく必要がある。
OnConnect
では、プロパティページが作成されたときに呼び出される。引数のIUnknown
インターフェイスはフィルタへのポインタになっている。QueryInterface
を使ってIColor
インターフェイスを問い合わせておく。
1 2 3 4 5 | HRESULT CMySourceExProp::OnConnect(IUnknown *pUnknown) {
HRESULT hr=pUnknown->QueryInterface(
__uuidof(IColor), (void**)&m_pColor);
return hr;
}
|
OnActivate
も同様にプロパティページが作成されたときに呼び出される。ここでのタスクはプロパティページのUIの初期化を行うことである。Icolor::GetColor
を呼び出し現在値をm_CurrVal
に取得し UI を初期化する。
1 2 3 4 5 6 7 | HRESULT CMySourceExProp::OnActivate(void) {
InitCommonControls();
m_pColor->GetColor(&m_CurrVal);
SendDlgItemMessage(m_Dlg, IDC_SLIDER1, TBM_SETRANGE, 0,MAKELONG(0, 255));
SendDlgItemMessage(m_Dlg, IDC_SLIDER1, TBM_SETPOS, 1, m_CurrVal);
return S_OK;
}
|
OnReceiveMessage
はメッセージプロシージャである。スライダーコントロールを操作するとメンバ変数 m_NewVal
が更新される。IColor::SetColor
を呼び出し、すぐに画面に反映されるようにしておく。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | BOOL CMySourceExProp::OnReceiveMessage
(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg) {
case WM_HSCROLL:
switch(LOWORD(wParam)) {
case TB_PAGEDOWN:
case SB_THUMBTRACK:
case TB_PAGEUP:
m_NewVal=SendDlgItemMessage(m_Dlg, IDC_SLIDER1,
TBM_GETPOS, 0, 0);
m_pColor->SetColor(m_NewVal);
__super::m_bDirty=TRUE;
if(__super::m_pPageSite) {
__super::m_pPageSite->OnStatusChange(PROPPAGESTATUS_DIRTY);
}
}
return (LRESULT)1;
}
return CBasePropertyPage::OnReceiveMessage(hwnd,uMsg,wParam,lParam);
}
|
OnApplyChanges
は Apply ボタンや OK ボタンが押下されたときに呼び出される。メンバ変数 m_CurrVal
に m_NewVal
を代入する。
1 2 3 4 | HRESULT CMySourceExProp::OnApplyChanges(void) {
m_CurrVal=m_NewVal;
return S_OK;
}
|
OnDisconnect
はプロパティページが閉じられるときに呼び出される。メンバ変数 m_CurrVal
で IColor::SetColor
を呼び出す。そして取得したインターフェイスを解放する。
もしユーザが Cancel ボタンを押下した場合、OnApplyChanges
が呼び出されないためm_CurrVal
は更新されていないことになる。つまりスライダーを動かす前の値に戻ることになる。
1 2 3 4 5 6 7 8 | HRESULT CMySourceExProp::OnDisconnect(void) {
if(m_pColor) {
m_pColor->SetColor(m_CurrVal);
m_pColor->Release();
m_pColor=NULL;
}
return S_OK;
}
|
使い方
regsvr32 でフィルタを登録したら graphedit で確認してみよう。
フィルタグラフを実行したままプロパティページを開き、スライダーを動かすと明るさが変化することを確認できる。
Comments
comments powered by Disqus