DirectShow过滤器开发-抓取样本过滤器

下载本过滤器DLL
在过滤器的开发中,有时,我们需要抓取过滤器引脚输出的样本,对样本数据进行分析,获取样本的有效数据长度,时间戳,媒体时间,中断标志,同步点标志,预卷标志。出于此种考虑,开发了此过滤器。将样本的所有参数,通过列表直观的显示出来,同时还可以抓取样本数据,输出到磁盘。下面是此过滤器的样本信息窗口图片:
在这里插入图片描述

还可以在连接引脚时,指定连接使用的媒体类型。
在这里插入图片描述

过滤器的参数信息

过滤器名称:采样
过滤器GUID:{484DFA06-F5D3-48AF-9AA0-6E3188F9F4C3}
DLL注册函数名:DllRegisterServer
删除注册函数名:DllUnregisterServer
过滤器有1个输入引脚。
输入引脚标识:In
输入引脚媒体类型:
主要类型:GUID_NULL
子类型:GUID_NULL
格式类型:GUID_NULL
在一个过滤器图中,最多可以创建10个此采样过滤器。

过滤器开发过程

过滤器从CBaseFilter派生。重写了Run,JoinFilterGraph,GetPinCount,GetPin函数。添加了GetString,GetMediaTypeString,GetFormatString自定义函数。

GetString函数,用于从GUID获取其定义字符串。
首先创建一个M.dat文件,创建方法是:首先,写入一个int值,占4字节,其包含了项的总数。然后写入每一项。
每项的结构是:先写入一个DWORD值,占4字节,其包含了该项“GUID定义“字符串的长度(包含空终止符),然后写入“GUID定义“字符串;最后写入与该定义对应的GUID的字符形式,占39字节(包含空终止符)。

DWORD(16)MEDIATYPE_Video {73646976-0000-0010-8000-00AA00389B71}
DWORD(18)MEDIASUBTYPE_H264 {34363248-0000-0010-8000-00AA00389B71}

DWORD(16)MEDIATYPE_Audio {73647561-0000-0010-8000-00AA00389B71}

将有定义的媒体类型主要类型,子类型,格式类型的定义字符串和其字符形式的GUID,分别写入项。这些GUID获取自uuids.h,wmcodecdsp.h,ksuuids.h,dxva.h,Bdamedia.h头文件。
准备好M.dat文件后,将其添加到资源。然后加载资源,获取资源地址。将,要获取其定义的GUID转换为字符形式,与M.dat文件中每一项的GUID的字符形式进行对比,如果相同,返回与其对应的定义字符串。具体代码如下:

char* CFilter::GetString(GUID guid)//获取GUID定义字符串
{
	LPWSTR lp=NULL;
	HRESULT hr = StringFromCLSID(guid, (LPOLESTR*)&lp);//将GUID转换为字符串形式
	char* chX=new char[39];
	for(int i=0;i<39;i++)
	{
		chX[i]=(char)lp[i];
	}
	CoTaskMemFree(lp);//释放StringFromCLSID分配的内存
    HRSRC hRes=FindResource(Hinstance,MAKEINTRESOURCE(IDR_DAT1),L"DAT");
    HGLOBAL hMem=LoadResource(Hinstance,hRes);
    BYTE* pb=(BYTE*)LockResource(hMem);//获取数据的起始内存地址
    DWORD count, LEN; char ch[39];
	CopyMemory(&count,pb,4);pb+=4;
	for (int i = 0; i < (int)count; i++)
	{
		CopyMemory(&LEN,pb,4);pb+=4;
		char* pch = new char[LEN];
		CopyMemory(pch,pb,LEN);pb+=LEN;
		memset(ch, 0, 39);
		CopyMemory(ch,pb,39);pb+=39;
		if(strcoll(chX,ch)==0)//如果字符串相等
		{
			FreeResource(hMem);//释放资源
			delete[] chX;
			return pch;
		}
		delete[] pch;
	}
    FreeResource(hMem);//释放资源
	return chX;
}

GetMediaTypeString函数获取媒体类型描述字符串。
GetFormatString函数获取格式结构描述字符串。
创建了自定义过滤器指针数组类,管理过滤器指针。
创建了过滤器名称数组类,为过滤器指定名称。
将10个过滤器名称,保存在wchar_t WCH[10][20]二维数组中:
采样 1 FALSE
采样 2 FALSE
采样 3 FALSE
采样 4 FALSE
采样 5 FALSE
采样 6 FALSE
采样 7 FALSE
采样 8 FALSE
采样 9 FALSE
采样 10 FALSE
同时创建BOOL变量数组,标记名称是否已使用。TRUE表示已使用,FALSE未使用。GetName函数获取过滤器名称,它从1到10遍历每个名称,当该名称标记为FALSE时,返回该名称的地址,并将该名称标记设置为TRUE。
在过滤器的构造函数中,创建线程,用于创建样本信息窗口,并在窗口中创建要使用的控件,为窗口添加窗口过程函数。安装键盘消息钩子,当按F2键时,显示样本信息窗口。

输入引脚从CBaseInputPin派生。重写了CheckConnect,CheckMediaType,SetMediaType,Receive函数。在引脚开始连接时,CheckConnect最先调用,参数pPin为对方引脚的指针。在CheckConnect函数中,枚举对方引脚的所有媒体类型,并将获取到的媒体类型指针,和媒体类型描述字符串,添加到自定义数组。在CheckMediaType函数的首次调用中,弹出媒体类型选择模态对话框。为对话框添加过程函数,在对话框的初始化中,从自定义数组加载媒体类型项,到对话框的列表视图控件,用于选择连接使用的媒体类型。在SetMediaType函数中,将媒体类型描述文本,指定给样本信息窗口中的编辑框。Receive函数接收上游输出引脚发送的样本。在该函数中,获取样本所有信息,并将信息文本指定给样本信息窗口中的列表视图控件;如果需要,复制样本数据写到磁盘文件。

下面是本过滤器DLL的全部代码:

DLL头文件:GetSample.h

#ifndef  DLL_FILE
#define DLL_FILE

#include "resource.h"

#include <streams.h>
#include <initguid.h>

#if _DEBUG
	#pragma comment(lib, "Strmbasd.lib")//C:\Program Files\Microsoft SDKs\Windows\v7.1\Samples\multimedia\directshow\baseclasses\Debug\strmbasd.lib
#else
	#pragma comment(lib, "Strmbase.lib")//C:\Program Files\Microsoft SDKs\Windows\v7.1\Samples\multimedia\directshow\baseclasses\Release\strmbase.lib
#endif
#pragma comment(lib, "Winmm.lib")//C:\Program Files\Microsoft SDKs\Windows\v7.1\Lib\Winmm.lib
#pragma comment(lib, "msvcrt.lib")//C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\lib\msvcrt.lib

// {484DFA06-F5D3-48AF-9AA0-6E3188F9F4C3}
DEFINE_GUID(CLSID_GetSample, 
0x484dfa06, 0xf5d3, 0x48af, 0x9a, 0xa0, 0x6e, 0x31, 0x88, 0xf9, 0xf4, 0xc3);

#endif // DLL_FILE

DLL源文件:GetSample.cpp

#include "GetSample.h"
#include "CFilter.h"

HINSTANCE Hinstance;//DLL模块句柄

const AMOVIESETUP_MEDIATYPE sudPinTypes =
{
    &MEDIATYPE_NULL,            // 主要类型
    &MEDIASUBTYPE_NULL          // 子类型
};

const AMOVIESETUP_PIN sudPin  =  // 引脚信息
{
	L"In",                       //引脚名称
	FALSE,                       // 必须渲染输入引脚
	FALSE,                       // 输出引脚
	FALSE,                       // 具有该引脚的零个实例
	FALSE,                       // 可以创建一个以上引脚的实例
	&CLSID_NULL,                 //该引脚连接的过滤器的类标识
	NULL,                        //该引脚连接的引脚名称
	1,                           //引脚支持的媒体类型数
	&sudPinTypes                 //媒体类型信息
};   

const AMOVIESETUP_FILTER GetSample =  //过滤器的注册信息
{
    &CLSID_GetSample,            //过滤器的类标识
    L"采样",                      //过滤器的名称
    MERIT_DO_NOT_USE,            //过滤器优先值
    1,                           //引脚数量
    &sudPin                      //引脚信息
};

CFactoryTemplate g_Templates []  = {
    {
		L"采样"
      , &CLSID_GetSample
      , CFilter::CreateInstance
      , NULL
      , &GetSample
	}
};

int g_cTemplates = 1;

STDAPI DllRegisterServer()//注册DLL
{
    return AMovieDllRegisterServer2(TRUE);
} 

STDAPI DllUnregisterServer()//删除DLL注册
{
    return AMovieDllRegisterServer2(FALSE);
}

extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);

BOOL APIENTRY DllMain(HANDLE hModule, DWORD  dwReason, LPVOID lpReserved)
{
	Hinstance=(HINSTANCE)hModule;
    return DllEntryPoint((HINSTANCE)(hModule), dwReason, lpReserved);
}

过滤器头文件:CFilter.h

#ifndef  FILTER_FILE
#define FILTER_FILE

#include "GetSample.h"
#include "CInputPin.h"

class CFilter : public CBaseFilter, public CCritSec
{
	friend class CInputPin;
public:
    CFilter(LPWSTR lpName, LPUNKNOWN pUnk,HRESULT *phr);
    virtual ~CFilter();
    DECLARE_IUNKNOWN
	static CUnknown * WINAPI CreateInstance(LPUNKNOWN, HRESULT *);
    STDMETHODIMP Run(REFERENCE_TIME tStart);
    STDMETHODIMP JoinFilterGraph(IFilterGraph * pGraph, LPCWSTR pName);
    int GetPinCount();
    CBasePin *GetPin(int n);
	char* GetString(GUID guid);//获取GUID定义字符串
	char *GetMediaTypeString(const CMediaType *pmt);//获取媒体类型描述字符串
	char* GetFormatString(GUID guid, BYTE* P);//获取格式结构描述字符串
	int index;//样本索引
	int sel;//选择的媒体类型索引
	DWORD StartTime;//运行开始时间,单位毫秒
	HWND hSampleDlg;//样本信息窗口句柄
	HWND hPathEdit;//显示输出文件夹路径编辑框
	HWND hwndButton;//按钮窗口句柄
	HWND hEdit;//媒体类型编辑框窗口句柄
	HWND hL;//样本参数列表窗口句柄
	HMENU hMenu;//菜单句柄
	HFONT hFont1,hFont2;
	wchar_t DirectoryName[MAX_PATH];//数据文件夹路径
	wchar_t FilterName[20];//过滤器名称
	int Setup;//设置选项索引
	BOOL B100;//100数量限制标志
	HANDLE hHasCreate;//"样本信息窗口创建完成"事件句柄
    CInputPin *m_pInputPin;   //输入引脚指针
}; 

class CFilterPtr//过滤器指针数组类
{
public:
	CFilterPtr();
	DWORD dw[10];
	int Count;
	int Find(DWORD* p);//查找某个过滤器指针的索引
	void Add(DWORD* p);//添加过滤器指针
	void Delete(DWORD* p);//删除过滤器指针
	DWORD GetAt(int i);//获取指定索引处的过滤器指针
	int GetCount();//获取数组元素数量
};

class CName//过滤器名称数组类
{
public:
	CName();
	wchar_t WCH[10][20];//保存名称的2维数组
	BOOL Use[10];//名称使用标记数组,元素为TRUE,已使用;FALSE,未使用
	int Count;//已使用名称的数量
	int GetCount();//获取数组元素数量
	wchar_t* GetName();//从数组中获取可用名称
	void Delete(wchar_t* p);//在名称数组中删除参数指定的项(标记p未使用。已使用数量-1)
	wchar_t* GetAt(int i);//在名称数组中,获取指定索引处的名称
};

#endif // FILTER_FILE

过滤器源文件:CFilter.cpp

#include "CFilter.h"
#include "Commctrl.h"
#include "wchar.h"
#include "stdio.h"
#include "Dvdmedia.h"
#include "Mmreg.h"
#include "Mpegtype.h"
#include "Shlobj.h"//文件夹选择对话框使用

CFilterPtr::CFilterPtr()//过滤器指针数组类构造函数
{
	Count=0;
	for(int i=0;i<10;i++)
	{
		dw[i]=0;
	}
}

int CFilterPtr::Find(DWORD* p)//根据过滤器指针,获取其索引
{
	for(int i=0;i<Count;i++)
	{
		if(dw[i]==(DWORD)p)return i;
	}
	return -1;
}

void CFilterPtr::Add(DWORD* p)//向过滤器指针数组,添加过滤器指针
{
	if(Count==10)return;//最多添加10个过滤器指针
	dw[Count]=(DWORD)p;
	Count++;
}

void CFilterPtr::Delete(DWORD* p)//删除参数指定的过滤器指针
{
	int find=Find(p);
	if(find==-1)return;
	for(int i=find;i<Count-1;i++)
	{
		dw[i]=dw[i+1];
	}
	Count--;
	for(int i=Count;i<10;i++)//将后面的元素置0
	{
		dw[i]=0;
	}
}

int CFilterPtr::GetCount()//获取过滤器指针数组中,保存的指针的数量
{
	return Count;
}

DWORD CFilterPtr::GetAt(int i)//获取过滤器指针数组中,指定索引处的指针
{
	return dw[i];
}

CName::CName()//过滤器名称数组类构造函数
{
	Count=0;
	for(int i=0;i<10;i++)
	{
		Use[i]=FALSE;
		wmemset(WCH[i],0,20);
		wcscat_s(WCH[i],20,L"采样 ");
		wchar_t wch[4];
		_itow_s(i+1,wch,20,10);
		wcscat_s(WCH[i],20,wch);
	}
}

int CName::GetCount()//获取过滤器名称数组中,已使用名称的总数
{
	int n=0;
	for(int i=0;i<10;i++)
	{
		if(Use[i])n++;
	}
	return n;
}

wchar_t* CName::GetName()//从数组中获取名称
{
	if(Count==10)return NULL;
	wchar_t* pwch=NULL;
	for(int i=0;i<10;i++)
	{
		if(Use[i]==FALSE)
		{
			Use[i]=TRUE;pwch=WCH[i];break;
		}
	}
	Count++;
	return pwch;
}

void CName::Delete(wchar_t* p)//从数组中,删除参数指定的名称(实际为,标记该名称未使用)
{
	if(Count==0)return;
	for(int i=0;i<10;i++)
	{
		if(wcscmp(WCH[i],p)==0)
		{
			Use[i]=FALSE;Count--;return;
		}
	}
}

wchar_t* CName::GetAt(int i)//获取指定索引处的名称
{
	return WCH[i];
}

CFilterPtr FilterArray;//过滤器指针数组对象
CName NameArray;//过滤器名称数组对象

extern HINSTANCE Hinstance;//DLL模块句柄
HHOOK hHook=NULL;//键盘消息钩子句柄

LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);//样本信息窗口过程函数声明

DWORD WINAPI  CreateWindowThread(LPVOID pParam);//“创建样本信息窗口”线程函数声明

LRESULT CALLBACK LowLevelKeyboardProc(int  nCode, WPARAM wParam, LPARAM lParam);//钩子过程函数声明

#pragma warning(disable:4355 4127)//禁用警告C4355

CFilter::CFilter(LPWSTR lpName, LPUNKNOWN pUnk,HRESULT *phr) : CBaseFilter(lpName, pUnk, (CCritSec *) this, CLSID_GetSample)
{
	wmemset(FilterName,0,20);wcscat_s(FilterName,20,lpName);//将过滤器名称赋值给FilterName
	wmemset(DirectoryName,0,MAX_PATH);
	wcscat_s(DirectoryName,MAX_PATH,L"D:\\");
	wcscat_s(DirectoryName,MAX_PATH, FilterName);//以过滤器名称,作为文件夹名称
	CreateDirectory(DirectoryName,NULL);//创建数据输出文件夹
	hHasCreate=CreateEvent( NULL, TRUE, FALSE, NULL); //创建事件,手动重置,初始状态无信号
	hSampleDlg=NULL;hEdit=NULL;hL=NULL;B100=TRUE;
	hFont1 = CreateFont(20,0,0,0,FW_DONTCARE,FALSE,FALSE,FALSE,DEFAULT_CHARSET,OUT_OUTLINE_PRECIS,CLIP_DEFAULT_PRECIS,CLEARTYPE_QUALITY, VARIABLE_PITCH,TEXT("微软雅黑"));
	hFont2 = CreateFont(18,0,0,0,FW_DONTCARE,FALSE,FALSE,FALSE,DEFAULT_CHARSET,OUT_OUTLINE_PRECIS,CLIP_DEFAULT_PRECIS,CLEARTYPE_QUALITY, VARIABLE_PITCH,TEXT("微软雅黑"));
	CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)CreateWindowThread,this,0,NULL);//创建“创建样本信息窗口”线程,将过滤器地址作为线程参数
	if(hHook==NULL)
		hHook = SetWindowsHookEx(WH_KEYBOARD_LL, &LowLevelKeyboardProc, (HINSTANCE)NULL, 0);//安装键盘消息钩子
    m_pInputPin = new CInputPin(this,phr,L"In");//创建输入引脚
    if(m_pInputPin == NULL)
    {
        if (phr)
            *phr = E_OUTOFMEMORY;
    }
} 

CFilter::~CFilter()
{
	CloseHandle(hHasCreate);
	SendMessage(hSampleDlg,WM_CLOSE,0,0);//关闭样本信息窗口
	DestroyWindow(hSampleDlg);//销毁样本信息窗口
	NameArray.Delete(FilterName);//标记FileName中过滤器名称未使用
	FilterArray.Delete((DWORD*)this);//从数组中删除该过滤器指针
	if(FilterArray.GetCount()==0)//如果过滤器指针数组元素数为0
	{
		UnhookWindowsHookEx(hHook);//删除钩子
		hHook=NULL;
		UnregisterClass(L"样本信息窗口类", Hinstance);//删除窗口类注册
	}
}

CUnknown * WINAPI CFilter::CreateInstance(LPUNKNOWN pUnk, HRESULT *phr)
{
	if(FilterArray.GetCount()==10)
	{
		MessageBox(0,L"最多创建10个采样过滤器",0,MB_OK);*phr=S_FALSE;return NULL;
	}
    return new CFilter(NameArray.GetName(), pUnk, phr);//创建过滤器
} 

STDMETHODIMP CFilter::Run(REFERENCE_TIME tStart)
{
    HRESULT hr = NOERROR;
    hr = CBaseFilter::Run(tStart);
    if(FAILED(hr)) return hr;
	index=0;
	StartTime=timeGetTime();
	SendMessage(hL,LVM_DELETEALLITEMS,0,0);//在样本信息窗口中,删除样本参数列表所有项
    return NOERROR;
} 

STDMETHODIMP CFilter::JoinFilterGraph(IFilterGraph * pGraph, LPCWSTR pName)
{
	if(pGraph!=NULL)
	{
		pName=FilterName;
	}
	return CBaseFilter::JoinFilterGraph(pGraph, pName);
}

int CFilter::GetPinCount()
{
    return 1;
}

CBasePin *CFilter::GetPin(int n)
{
    if(n != 0)
    {
        return NULL;
    }
    return m_pInputPin;
} 

char* CFilter::GetString(GUID guid)//获取GUID定义字符串
{
	LPWSTR lp=NULL;
	HRESULT hr = StringFromCLSID(guid, (LPOLESTR*)&lp);//将GUID转换为字符串形式
	char* chX=new char[39];
	for(int i=0;i<39;i++)
	{
		chX[i]=(char)lp[i];
	}
	CoTaskMemFree(lp);//释放StringFromCLSID分配的内存
    HRSRC hRes=FindResource(Hinstance,MAKEINTRESOURCE(IDR_DAT1),L"DAT");
    HGLOBAL hMem=LoadResource(Hinstance,hRes);
    BYTE* pb=(BYTE*)LockResource(hMem);//获取数据的起始内存地址
    DWORD count, LEN; char ch[39];
	CopyMemory(&count,pb,4);pb+=4;
	for (int i = 0; i < (int)count; i++)
	{
		CopyMemory(&LEN,pb,4);pb+=4;
		char* pch = new char[LEN];
		CopyMemory(pch,pb,LEN);pb+=LEN;
		memset(ch, 0, 39);
		CopyMemory(ch,pb,39);pb+=39;
		if(strcoll(chX,ch)==0)//如果字符串相等
		{
			FreeResource(hMem);//释放资源
			delete[] chX;
			return pch;
		}
		delete[] pch;
	}
    FreeResource(hMem);//释放资源
	return chX;
}

char* CFilter::GetMediaTypeString(const CMediaType *pmt)//获取媒体类型描述字符串
{
	char* ch=new char[2000];
	char* pMain=GetString(pmt->majortype);//主要类型
	char* pSub=GetString(pmt->subtype);//子类型
	char* pFormat=GetString(pmt->formattype);//格式类型
	memset(ch,0,2000);
	strcat_s(ch,2000,"主要类型:\t");//strcat_s在char字符串后附加字符串
	strcat_s(ch,2000,pMain);
	strcat_s(ch,2000,"\r\n");
	strcat_s(ch,2000,"子类型:\t\t");
	strcat_s(ch,2000,pSub);
	strcat_s(ch,2000,"\r\n");
	strcat_s(ch,2000,"格式类型:\t");
	strcat_s(ch,2000,pFormat);
	strcat_s(ch,2000,"\r\n");
	if(pmt->bFixedSizeSamples)
		strcat_s(ch,2000,"样本为固定大小:\tTRUE\r\n");
	else
		strcat_s(ch,2000,"样本为固定大小:\tFALSE\r\n");
	if(pmt->bTemporalCompression)
		strcat_s(ch,2000,"使用时间压缩:\tTRUE\r\n");
	else
		strcat_s(ch,2000,"使用时间压缩:\tFALSE\r\n");
	char cch[50];
	sprintf_s(cch,50, "格式块大小:\t%u\r\n",pmt->cbFormat);
	strcat_s(ch,2000,cch);
	delete[] pMain;delete[] pSub;delete[] pFormat;
	char* pFormatString=GetFormatString(pmt->formattype, pmt->pbFormat);
	strcat_s(ch,2000, pFormatString );
	delete[] pFormatString;
	return ch;
}

char* CFilter::GetFormatString(GUID guid, BYTE* P)//获取格式结构描述字符串
{
	if(P==NULL)return NULL;
	char* cch=new char[1000];
	memset(cch,0,1000);
	if (guid == FORMAT_DvInfo)
	{
		DVINFO* p = (DVINFO*)P;
		int  j;
		j  = sprintf_s( cch, 1000,     "格式结构:\tDVINFO\r\n");
		j += sprintf_s( cch + j, 1000 - j,  "\t\tdwDVAAuxSrc=%u\r\n", p->dwDVAAuxSrc );
		j += sprintf_s( cch + j, 1000 - j, "\t\tdwDVAAuxCtl=%u\r\n", p->dwDVAAuxCtl );
		j += sprintf_s( cch + j, 1000 - j,  "\t\tdwDVAAuxSrc1=%u\r\n", p->dwDVAAuxSrc1 );
		j += sprintf_s( cch + j, 1000 - j, "\t\tdwDVAAuxCtl1=%u\r\n", p->dwDVAAuxCtl1 );
		j += sprintf_s( cch + j, 1000 - j,  "\t\tdwDVVAuxSrc=%u\r\n", p->dwDVVAuxSrc );
		j += sprintf_s( cch + j, 1000 - j, "\t\tdwDVVAuxCtl=%u\r\n", p->dwDVVAuxCtl );
		j += sprintf_s( cch + j, 1000 - j, "\t\tdwDVReserved[0]=%u\r\n", p->dwDVReserved[0] );
		j += sprintf_s( cch + j, 1000 - j, "\t\tdwDVReserved[1]=%u\r\n", p->dwDVReserved[1] );
	}
	if (guid == FORMAT_MPEG2Video)
	{
		MPEG2VIDEOINFO* p = (MPEG2VIDEOINFO*)P;
		int  j;
		j  = sprintf_s( cch, 1000,     "格式结构:\tMPEG2VIDEOINFO\r\n");
		j += sprintf_s( cch + j, 1000 - j,  "\t\thdr=VIDEOINFOHEADER2\r\n" );
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.rcSource={%d, ", p->hdr.rcSource.left );
		j += sprintf_s( cch + j, 1000 - j, "%d, ", p->hdr.rcSource.top );
		j += sprintf_s( cch + j, 1000 - j, "%d, ", p->hdr.rcSource.right );
		j += sprintf_s( cch + j, 1000 - j, "%d}\r\n", p->hdr.rcSource.bottom );
		j += sprintf_s( cch + j, 1000 - j,  "\t\thdr.rcTarget={%d, ", p->hdr.rcTarget.left );
		j += sprintf_s( cch + j, 1000 - j, "%d, ", p->hdr.rcTarget.top );
		j += sprintf_s( cch + j, 1000 - j, "%d, ", p->hdr.rcTarget.right );
		j += sprintf_s( cch + j, 1000 - j, "%d}\r\n", p->hdr.rcTarget.bottom );
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.dwBitRate=%u\r\n", p->hdr.dwBitRate );
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.dwBitErrorRate=%u\r\n", p->hdr.dwBitErrorRate );
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.AvgTimePerFrame=%I64d\r\n", p->hdr.AvgTimePerFrame );
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.dwInterlaceFlags=%u\r\n", p->hdr.dwInterlaceFlags );
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.dwCopyProtectFlags=%u\r\n", p->hdr.dwCopyProtectFlags );
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.dwPictAspectRatioX=%u\r\n", p->hdr.dwPictAspectRatioX );
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.dwPictAspectRatioY=%u\r\n", p->hdr.dwPictAspectRatioY );
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.dwControlFlags=%u\r\n", p->hdr.dwControlFlags );
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.dwReserved1=%u\r\n", p->hdr.dwReserved1 );
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.dwReserved2=%u\r\n", p->hdr.dwReserved2 );
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.bmiHeader=BITMAPINFOHEADER\r\n" );
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.bmiHeader.biSize=%u\r\n", p->hdr.bmiHeader.biSize );
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.bmiHeader.biWidth=%d\r\n", p->hdr.bmiHeader.biWidth );
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.bmiHeader.biHeight=%d\r\n", p->hdr.bmiHeader.biHeight );
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.bmiHeader.biPlanes=%d\r\n", p->hdr.bmiHeader.biPlanes );
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.bmiHeader.biBitCount=%d\r\n", p->hdr.bmiHeader.biBitCount );
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.bmiHeader.biCompression=%u\r\n", p->hdr.bmiHeader.biCompression );
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.bmiHeader.biSizeImage=%u\r\n", p->hdr.bmiHeader.biSizeImage );
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.bmiHeader.biXPelsPerMeter=%d\r\n", p->hdr.bmiHeader.biXPelsPerMeter );
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.bmiHeader.biYPelsPerMeter=%d\r\n", p->hdr.bmiHeader.biYPelsPerMeter );
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.bmiHeader.biClrUsed=%u\r\n", p->hdr.bmiHeader.biClrUsed );
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.bmiHeader.biClrImportant=%u\r\n", p->hdr.bmiHeader.biClrImportant );
		j += sprintf_s( cch + j, 1000 - j, "\t\tdwStartTimeCode=%u\r\n", p->dwStartTimeCode );
		j += sprintf_s( cch + j, 1000 - j, "\t\tcbSequenceHeader=%u\r\n", p->cbSequenceHeader );
		j += sprintf_s( cch + j, 1000 - j, "\t\tdwProfile=%u\r\n", p->dwProfile );
		j += sprintf_s( cch + j, 1000 - j, "\t\tdwLevel=%u\r\n", p->dwLevel );
		j += sprintf_s( cch + j, 1000 - j, "\t\tdwFlags=%u\r\n", p->dwFlags );
		j += sprintf_s( cch + j, 1000 - j, "\t\tdwSequenceHeader=%u\r\n", p->dwSequenceHeader );
	}
	if (guid == FORMAT_MPEGStreams)
	{
		AM_MPEGSYSTEMTYPE* p=(AM_MPEGSYSTEMTYPE*)P;
		int  j;
		j  = sprintf_s( cch, 1000,     "格式结构:\tAM_MPEGSYSTEMTYPE\r\n");
		j += sprintf_s( cch + j, 1000 - j, "\t\tdwBitRate=%u\r\n", p->dwBitRate );
		j += sprintf_s( cch + j, 1000 - j, "\t\tcStreams=%u\r\n", p->cStreams );	
		AM_MPEGSTREAMTYPE* pAm=p->Streams;
		j += sprintf_s( cch + j, 1000 - j, "\t\tStreams[n]=AM_MPEGSTREAMTYPE\r\n");
		j += sprintf_s( cch + j, 1000 - j, "\t\tStreams[0].dwStreamID=%u\r\n", pAm->dwStreamId );
		j += sprintf_s( cch + j, 1000 - j, "\t\tStreams[0].dwReserved=%u\r\n", pAm->dwReserved );
		j += sprintf_s( cch + j, 1000 - j, "\t\tStreams[0].mt=AM_MEDIA_TYPE\r\n");
		j += sprintf_s( cch + j, 1000 - j, "\t\tStreams[0].bFormat=%u\r\n", pAm->bFormat);
		for(int i=1;i<(int)(p->cStreams);i++)
		{
			pAm=AM_MPEGSTREAMTYPE_NEXT(pAm);
			j += sprintf_s( cch + j, 1000 - j, "\t\tStreams[%d]", i );
			j += sprintf_s( cch + j, 1000 - j, ".dwStreamID=%u\r\n", pAm->dwStreamId );
			j += sprintf_s( cch + j, 1000 - j, "\t\tStreams[%d]", i );
			j += sprintf_s( cch + j, 1000 - j, ".dwReserved=%u\r\n", pAm->dwReserved );			
			j += sprintf_s( cch + j, 1000 - j, "\t\tStreams[%d]", i );
			j += sprintf_s( cch + j, 1000 - j, ".mt=AM_MEDIA_TYPE\r\n");
			j += sprintf_s( cch + j, 1000 - j, "\t\tStreams[%d]", i );
			j += sprintf_s( cch + j, 1000 - j, ".bFormat=%u\r\n", pAm->bFormat);
		}
	}
	if (guid == FORMAT_MPEGVideo)
	{
		MPEG1VIDEOINFO* p = (MPEG1VIDEOINFO*)P;
		int  j;
		j  = sprintf_s( cch, 1000,     "格式结构:\tMPEG1VIDEOINFO\r\n");
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr=VIDEOINFOHEADER\r\n");
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.rcSource={%d, ", p->hdr.rcSource.left );
		j += sprintf_s( cch + j, 1000 - j, "%d, ", p->hdr.rcSource.top );
		j += sprintf_s( cch + j, 1000 - j, "%d, ", p->hdr.rcSource.right );
		j += sprintf_s( cch + j, 1000 - j, "%d}\r\n", p->hdr.rcSource.bottom );
		j += sprintf_s( cch + j, 1000 - j,  "\t\thdr.rcTarget={%d, ", p->hdr.rcTarget.left );
		j += sprintf_s( cch + j, 1000 - j, "%d, ", p->hdr.rcTarget.top );
		j += sprintf_s( cch + j, 1000 - j, "%d, ", p->hdr.rcTarget.right );
		j += sprintf_s( cch + j, 1000 - j, "%d}\r\n", p->hdr.rcTarget.bottom );
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.dwBitRate=%u\r\n", p->hdr.dwBitRate );
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.dwBitErrorRate=%u\r\n", p->hdr.dwBitErrorRate );
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.AvgTimePerFrame=%I64d\r\n", p->hdr.AvgTimePerFrame );
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.bmiHeader=BITMAPINFOHEADER\r\n" );
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.bmiHeader.biSize=%u\r\n", p->hdr.bmiHeader.biSize );
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.bmiHeader.biWidth=%d\r\n", p->hdr.bmiHeader.biWidth );
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.bmiHeader.biHeight=%d\r\n", p->hdr.bmiHeader.biHeight );
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.bmiHeader.biPlanes=%d\r\n", p->hdr.bmiHeader.biPlanes );
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.bmiHeader.biBitCount=%d\r\n", p->hdr.bmiHeader.biBitCount );
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.bmiHeader.biCompression=%u\r\n", p->hdr.bmiHeader.biCompression);
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.bmiHeader.biSizeImage=%u\r\n", p->hdr.bmiHeader.biSizeImage );
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.bmiHeader.biXPelsPerMeter=%d\r\n", p->hdr.bmiHeader.biXPelsPerMeter );
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.bmiHeader.biYPelsPerMeter=%d\r\n", p->hdr.bmiHeader.biYPelsPerMeter );
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.bmiHeader.biClrUsed=%u\r\n", p->hdr.bmiHeader.biClrUsed );
		j += sprintf_s( cch + j, 1000 - j, "\t\thdr.bmiHeader.biClrImportant=%u\r\n", p->hdr.bmiHeader.biClrImportant );
		j += sprintf_s( cch + j, 1000 - j, "\t\tdwStartTimeCode=%u\r\n", p->dwStartTimeCode );
		j += sprintf_s( cch + j, 1000 - j, "\t\tcbSequenceHeader=%u\r\n", p->cbSequenceHeader );
		j += sprintf_s( cch + j, 1000 - j, "\t\tbSequenceHeader=%u\r\n", p->bSequenceHeader );
	}
	if(guid==FORMAT_VideoInfo)
	{
		VIDEOINFOHEADER* p = (VIDEOINFOHEADER*)P;
		int  j;
		j  = sprintf_s( cch, 1000,     "格式结构:\tVIDEOINFOHEADER\r\n");
		j += sprintf_s( cch + j, 1000 - j,     "\t\trcSource={%d, ", p->rcSource.left );
		j += sprintf_s( cch + j, 1000 - j, "%d, ", p->rcSource.top );
		j += sprintf_s( cch + j, 1000 - j, "%d, ", p->rcSource.right );
		j += sprintf_s( cch + j, 1000 - j, "%d}\r\n", p->rcSource.bottom );
		j += sprintf_s( cch + j, 1000 - j,  "\t\trcTarget={%d, ", p->rcTarget.left );
		j += sprintf_s( cch + j, 1000 - j, "%d, ", p->rcTarget.top );
		j += sprintf_s( cch + j, 1000 - j, "%d, ", p->rcTarget.right );
		j += sprintf_s( cch + j, 1000 - j, "%d}\r\n", p->rcTarget.bottom );
		j += sprintf_s( cch + j, 1000 - j, "\t\tdwBitRate=%u\r\n", p->dwBitRate );
		j += sprintf_s( cch + j, 1000 - j, "\t\tdwBitErrorRate=%u\r\n", p->dwBitErrorRate );
		j += sprintf_s( cch + j, 1000 - j, "\t\tAvgTimePerFrame=%I64d\r\n", p->AvgTimePerFrame );
		j += sprintf_s( cch + j, 1000 - j, "\t\tbmiHeader=BITMAPINFOHEADER\r\n" );
		j += sprintf_s( cch + j, 1000 - j, "\t\tbmiHeader.biSize=%u\r\n", p->bmiHeader.biSize );
		j += sprintf_s( cch + j, 1000 - j, "\t\tbmiHeader.biWidth=%d\r\n", p->bmiHeader.biWidth );
		j += sprintf_s( cch + j, 1000 - j, "\t\tbmiHeader.biHeight=%d\r\n", p->bmiHeader.biHeight );
		j += sprintf_s( cch + j, 1000 - j, "\t\tbmiHeader.biPlanes=%d\r\n", p->bmiHeader.biPlanes );
		j += sprintf_s( cch + j, 1000 - j, "\t\tbmiHeader.biBitCount=%d\r\n", p->bmiHeader.biBitCount );
		j += sprintf_s( cch + j, 1000 - j, "\t\tbmiHeader.biCompression=%u\r\n", p->bmiHeader.biCompression);
		j += sprintf_s( cch + j, 1000 - j, "\t\tbmiHeader.biSizeImage=%u\r\n", p->bmiHeader.biSizeImage );
		j += sprintf_s( cch + j, 1000 - j, "\t\tbmiHeader.biXPelsPerMeter=%d\r\n", p->bmiHeader.biXPelsPerMeter );
		j += sprintf_s( cch + j, 1000 - j, "\t\tbmiHeader.biYPelsPerMeter=%d\r\n", p->bmiHeader.biYPelsPerMeter );
		j += sprintf_s( cch + j, 1000 - j, "\t\tbmiHeader.biClrUsed=%u\r\n", p->bmiHeader.biClrUsed );
		j += sprintf_s( cch + j, 1000 - j, "\t\tbmiHeader.biClrImportant=%u\r\n", p->bmiHeader.biClrImportant );
	}
	if (guid == FORMAT_VideoInfo2)
	{
		VIDEOINFOHEADER2* p=(VIDEOINFOHEADER2*)P;
		int  j;
		j  = sprintf_s( cch, 1000,     "格式结构:\tVIDEOINFOHEADER2\r\n" );
		j += sprintf_s( cch + j, 1000 - j, "\t\trcSource={%d, ", p->rcSource.left );
		j += sprintf_s( cch + j, 1000 - j, "%d, ", p->rcSource.top );
		j += sprintf_s( cch + j, 1000 - j, "%d, ", p->rcSource.right );
		j += sprintf_s( cch + j, 1000 - j, "%d}\r\n", p->rcSource.bottom );
		j += sprintf_s( cch + j, 1000 - j,  "\t\trcTarget={%d, ", p->rcTarget.left );
		j += sprintf_s( cch + j, 1000 - j, "%d, ", p->rcTarget.top );
		j += sprintf_s( cch + j, 1000 - j, "%d, ", p->rcTarget.right );
		j += sprintf_s( cch + j, 1000 - j, "%d}\r\n", p->rcTarget.bottom );
		j += sprintf_s( cch + j, 1000 - j, "\t\tdwBitRate=%u\r\n", p->dwBitRate );
		j += sprintf_s( cch + j, 1000 - j, "\t\tdwBitErrorRate=%u\r\n", p->dwBitErrorRate );
		j += sprintf_s( cch + j, 1000 - j, "\t\tAvgTimePerFrame=%I64d\r\n", p->AvgTimePerFrame );
		j += sprintf_s( cch + j, 1000 - j, "\t\tdwInterlaceFlags=%u\r\n", p->dwInterlaceFlags );
		j += sprintf_s( cch + j, 1000 - j, "\t\tdwCopyProtectFlags=%u\r\n", p->dwCopyProtectFlags );
		j += sprintf_s( cch + j, 1000 - j, "\t\tdwPictAspectRatioX=%u\r\n", p->dwPictAspectRatioX );
		j += sprintf_s( cch + j, 1000 - j, "\t\tdwPictAspectRatioY=%u\r\n", p->dwPictAspectRatioY );
		j += sprintf_s( cch + j, 1000 - j, "\t\tdwControlFlags=%u\r\n", p->dwControlFlags );
		j += sprintf_s( cch + j, 1000 - j, "\t\tdwReserved1=%u\r\n", p->dwReserved1 );
		j += sprintf_s( cch + j, 1000 - j, "\t\tdwReserved2=%u\r\n", p->dwReserved2 );
		j += sprintf_s( cch + j, 1000 - j, "\t\tbmiHeader=BITMAPINFOHEADER\r\n" );
		j += sprintf_s( cch + j, 1000 - j, "\t\tbmiHeader.biSize=%u\r\n", p->bmiHeader.biSize );
		j += sprintf_s( cch + j, 1000 - j, "\t\tbmiHeader.biWidth=%d\r\n", p->bmiHeader.biWidth );
		j += sprintf_s( cch + j, 1000 - j, "\t\tbmiHeader.biHeight=%d\r\n", p->bmiHeader.biHeight );
		j += sprintf_s( cch + j, 1000 - j, "\t\tbmiHeader.biPlanes=%d\r\n", p->bmiHeader.biPlanes );
		j += sprintf_s( cch + j, 1000 - j, "\t\tbmiHeader.biBitCount=%d\r\n", p->bmiHeader.biBitCount );
		j += sprintf_s( cch + j, 1000 - j, "\t\tbmiHeader.biCompression=%u\r\n", p->bmiHeader.biCompression );
		j += sprintf_s( cch + j, 1000 - j, "\t\tbmiHeader.biSizeImage=%u\r\n", p->bmiHeader.biSizeImage );
		j += sprintf_s( cch + j, 1000 - j, "\t\tbmiHeader.biXPelsPerMeter=%d\r\n", p->bmiHeader.biXPelsPerMeter );
		j += sprintf_s( cch + j, 1000 - j, "\t\tbmiHeader.biYPelsPerMeter=%d\r\n", p->bmiHeader.biYPelsPerMeter );
		j += sprintf_s( cch + j, 1000 - j, "\t\tbmiHeader.biClrUsed=%u\r\n", p->bmiHeader.biClrUsed );
		j += sprintf_s( cch + j, 1000 - j, "\t\tbmiHeader.biClrImportant=%u\r\n", p->bmiHeader.biClrImportant );
	}
	if (guid == FORMAT_WaveFormatEx)
	{
		WAVEFORMATEX* p = (WAVEFORMATEX*)P;
		int  j;
		j  = sprintf_s( cch, 1000,     "格式结构:\tWAVEFORMATEX\r\n" );
		j += sprintf_s( cch + j, 1000 - j, "\t\twFormatTag=%d\r\n", p->wFormatTag );
		j += sprintf_s( cch + j, 1000 - j, "\t\tnChannels=%d\r\n", p->nChannels );
		j += sprintf_s( cch + j, 1000 - j, "\t\tnSamplesPerSec=%u\r\n", p->nSamplesPerSec );
		j += sprintf_s( cch + j, 1000 - j, "\t\tnAvgBytesPerSec=%u\r\n", p->nAvgBytesPerSec );
		j += sprintf_s( cch + j, 1000 - j, "\t\tnBlockAlign=%d\r\n", p->nBlockAlign );
		j += sprintf_s( cch + j, 1000 - j, "\t\twBitsPerSample=%d\r\n", p->wBitsPerSample );
		j += sprintf_s( cch + j, 1000 - j, "\t\tcbSize=%d\r\n", p->cbSize );
	}
	return cch;
}

void DeleteAllSamples(int sel)//删除数据输出文件夹中所有样本数据函数
{
	CFilter* m_pCFilter=(CFilter*)FilterArray.GetAt(sel);
	SHFILEOPSTRUCT ss;
	ss.hwnd=NULL;
	ss.wFunc =FO_DELETE;
	wchar_t wch[MAX_PATH];
	wmemset(wch,0,MAX_PATH);
	wcscat_s(wch,MAX_PATH,m_pCFilter->DirectoryName);
	wcscat_s(wch,MAX_PATH,L"\\*.dat");
	ss.pFrom =wch;
	ss.pTo =NULL;
	ss.fFlags=FOF_FILESONLY|FOF_SILENT;
	ss.fAnyOperationsAborted=NULL;
	ss.hNameMappings=NULL;
	ss.lpszProgressTitle=NULL;
	SHFileOperation(&ss);
}

COLORREF color1=RGB(230,210,182),color2=RGB(100,90,70),color3=RGB(240,255,255);
LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)//样本信息窗口过程函数
{
	int sel;//窗口在”过滤器指针数组“中的索引
	CFilter* m_pCFilter=NULL;HBRUSH hbrBkgnd=NULL,hbrBkgnd2=NULL,hbrBtn=NULL;
	for(int i=0;i<FilterArray.GetCount();i++)//确定窗口在”过滤器指针数组“中的索引
	{
		m_pCFilter=(CFilter*)FilterArray.GetAt(i);
		if(m_pCFilter!=NULL)
		{
			if(m_pCFilter->hSampleDlg==hwnd)//如果”过滤器指针数组“中的某项的样本列表窗口句柄,等于hwnd
			{
				sel=i;break;//确定句柄为hwnd的窗口的索引
			}
		}
	}	
	switch(uMsg)
	{
	case WM_COMMAND:
		switch(HIWORD(wParam)) 
		{
		case BN_CLICKED:
			{
				if(m_pCFilter==NULL)break;
				if((HWND)lParam==m_pCFilter->hwndButton)//如果点击了“更改”按钮
				{
					BROWSEINFO bi;
					char buffer[MAX_PATH];
					ZeroMemory(buffer, MAX_PATH);
					bi.hwndOwner = NULL;
					bi.pidlRoot = NULL;
					bi.pszDisplayName = LPWSTR(buffer);
					bi.lpszTitle = L"选择一个文件夹";
					bi.ulFlags = BIF_EDITBOX;   
					bi.lpfn = NULL;
					bi.lParam = 0;
					bi.iImage = 0;
					LPITEMIDLIST pList = NULL;
					if ((pList = SHBrowseForFolder(&bi)) != NULL)
					{
						wmemset(m_pCFilter->DirectoryName,0,MAX_PATH);
						SHGetPathFromIDList(pList, m_pCFilter->DirectoryName);
						size_t len=wcslen(m_pCFilter->DirectoryName);
						if(m_pCFilter->DirectoryName[len-1]!='\\')//如果最后一个字符不是"\"
							wcscat_s(m_pCFilter->DirectoryName,MAX_PATH, L"\\");//在字符串后面添加"\"
						wcscat_s(m_pCFilter->DirectoryName,MAX_PATH, m_pCFilter->FilterName);
						wchar_t wchPathName[MAX_PATH]=L" 输出文件夹:  ";
						wcscat_s(wchPathName,MAX_PATH,m_pCFilter->DirectoryName);
						SendMessage(m_pCFilter->hPathEdit,WM_SETTEXT,0,(LPARAM)wchPathName);
						CreateDirectory(m_pCFilter->DirectoryName,NULL);//创建数据输出文件夹
					}
				}
			}
			break;
		}
		switch(LOWORD(wParam)) //响应点击菜单项
		{ 
		case ID_Menu: //”清空列表“
			if(m_pCFilter==NULL)break;
			SendMessage(m_pCFilter->hL,LVM_DELETEALLITEMS,0,0);//列表视图删除所有项
			break; 
		case ID_40005: //”删除所有样本数据“
			if(m_pCFilter==NULL)break;
			DeleteAllSamples(sel);//删除所有样本数据
			break;
		case ID_40006: //”最多获取100个样本“
			if(m_pCFilter==NULL)break;
			if(m_pCFilter->B100)
			{
				CheckMenuItem(m_pCFilter->hMenu,ID_40006,MF_UNCHECKED);m_pCFilter->B100=FALSE;
			}
			else
			{
				CheckMenuItem(m_pCFilter->hMenu,ID_40006,MF_CHECKED);m_pCFilter->B100=TRUE;
			}
			break;
		case ID_40002: //”不获取样本数据“
			if(m_pCFilter==NULL)break;
			m_pCFilter->Setup=0;
			CheckMenuItem(m_pCFilter->hMenu,ID_40002,MF_CHECKED);CheckMenuItem(m_pCFilter->hMenu,ID_40003,MF_UNCHECKED);CheckMenuItem(m_pCFilter->hMenu,ID_40004,MF_UNCHECKED);
			break; 
		case ID_40003: //”只获取同步点样本数据“
			if(m_pCFilter==NULL)break;
			m_pCFilter->Setup=1;
			CheckMenuItem(m_pCFilter->hMenu,ID_40003,MF_CHECKED);CheckMenuItem(m_pCFilter->hMenu,ID_40002,MF_UNCHECKED);CheckMenuItem(m_pCFilter->hMenu,ID_40004,MF_UNCHECKED);
			break; 
		case ID_40004: //”获取所有样本数据“
			if(m_pCFilter==NULL)break;
			m_pCFilter->Setup=2;
			CheckMenuItem(m_pCFilter->hMenu,ID_40004,MF_CHECKED);CheckMenuItem(m_pCFilter->hMenu,ID_40002,MF_UNCHECKED);CheckMenuItem(m_pCFilter->hMenu,ID_40003,MF_UNCHECKED);
			break; 
		default:
			break; 
		} 
	case WM_CTLCOLORSTATIC://绘制只读编辑控件
        {
			if(m_pCFilter==NULL)break;
			HDC hdcStatic = (HDC) wParam;
			if((HWND)lParam==m_pCFilter->hEdit)//绘制显示媒体类型编辑框
			{
				SetTextColor(hdcStatic, color3);
				SetBkColor(hdcStatic, color2);
				if (hbrBkgnd == NULL)
				{
					hbrBkgnd = CreateSolidBrush(color2);
				}
				return (INT_PTR)hbrBkgnd;
			}
			if((HWND)lParam==m_pCFilter->hPathEdit)//绘制显示输出文件夹路径编辑框
			{
				SetTextColor(hdcStatic, RGB(123,36,6));
				SetBkColor(hdcStatic, color1);
				if (hbrBkgnd2 == NULL)
				{
					hbrBkgnd2 = CreateSolidBrush(color1);
				}
				return (INT_PTR)hbrBkgnd2;
			}
        }
		break;
	case WM_CTLCOLORBTN://绘制按钮
		{
			if(m_pCFilter==NULL)break;
			HDC hdcBtn = (HDC)wParam;
			HWND hBtn=(HWND)lParam;
			SetBkColor(hdcBtn, color1);
			SetTextColor(hdcBtn,RGB(123,36,6));
			RECT rect;
			GetClientRect(hBtn,&rect);
			SelectObject(hdcBtn,m_pCFilter->hFont2);
			DrawText(hdcBtn,L"更改",2,&rect,DT_CENTER|DT_VCENTER|DT_SINGLELINE);
			if(hbrBtn==NULL)
			{
				hbrBtn= CreateSolidBrush(color1);
			}
			return (INT_PTR)hbrBtn;
		}
		break;
	case WM_CLOSE://点击了样本窗口关闭按钮
		ShowWindow(hwnd, SW_HIDE);//隐藏窗口
		return 0;//不调用DefWindowProc,防止销毁窗口
	}
	return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

DWORD WINAPI  CreateWindowThread(LPVOID pParam)//创建"样本信息窗口”线程函数,pParam参数为过滤器指针
{
	CFilter* p=(CFilter*)pParam;
	WNDCLASSEX wcx;
	wcx.cbSize = sizeof(wcx);//结构的大小
	wcx.style = CS_HREDRAW | CS_VREDRAW; //窗口类样式
	wcx.lpfnWndProc = WndProc; //指向窗口过程
	wcx.cbClsExtra = 0;                //没有额外的类内存
	wcx.cbWndExtra = 0;            //没有额外的窗口内存
	wcx.hInstance = Hinstance;  //实例句柄
	wcx.hIcon = LoadIcon(NULL, IDI_APPLICATION);  //预定义的应用程序图标
	wcx.hCursor = LoadCursor(NULL, IDC_ARROW);   //预定义的光标
	HBRUSH hBrush=CreateSolidBrush(color2);
	wcx.hbrBackground = hBrush;  //背景笔刷
	wcx.lpszMenuName = L"MainMenu"; //菜单资源名称
	wcx.lpszClassName = L"样本信息窗口类"; //窗口类的名称
	wcx.hIconSm = (HICON)LoadImage(Hinstance, MAKEINTRESOURCE(5),IMAGE_ICON,GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),LR_DEFAULTCOLOR);//小类图标 
	RegisterClassEx(&wcx);//注册窗口类
	p->hMenu=LoadMenu(Hinstance,MAKEINTRESOURCE(IDR_MENU1));//加载菜单
	int ScreenWidth=GetSystemMetrics(SM_CXSCREEN);//获取主显示器的宽度,以像素为单位
	int ScreenHeight=GetSystemMetrics(SM_CYSCREEN);//获取主显示器的高度,以像素为单位
	int Width=600;int Height=800;//窗口的宽高
	HWND hwnd= CreateWindowEx(//创建"样本信息窗口"
		WS_EX_TOPMOST,          //窗口扩展样式      
		L"样本信息窗口类",       //类名                
		p->FilterName,          //窗口名称         
		WS_SYSMENU|WS_CAPTION|WS_CLIPCHILDREN|WS_MINIMIZEBOX|WS_POPUP,   //窗口样式      
		(ScreenWidth-Width)/2,    //水平居中
		(ScreenHeight-Height)/2,  //垂直居中
		Width,           //宽度        
		Height,          //高度       
		(HWND)NULL,      //没有父窗口或所有者窗口
		p->hMenu,        //使用的菜单      
		Hinstance,       //实例句柄     
		NULL);           //没有窗口创建数据

	RECT rect;
	GetClientRect(hwnd,&rect);
	wchar_t wchPathName[MAX_PATH]=L" 输出文件夹:  ";
	wcscat_s(wchPathName,MAX_PATH,p->DirectoryName);
	p->hPathEdit=CreateWindow(L"Edit", wchPathName,WS_CHILD|WS_VISIBLE| ES_READONLY ,5,5,rect.right-51,20,hwnd,NULL,Hinstance,NULL);//创建路径编辑框
	SendMessage(p->hPathEdit,WM_SETFONT,(WPARAM)p->hFont2,0);//给路径编辑框设置字体
	p->hwndButton = CreateWindow(L"BUTTON", L"更改", WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON|BS_OWNERDRAW , rect.right-45, 5, 40, 20, hwnd, NULL, Hinstance, NULL);//创建按钮
	p->hEdit=CreateWindow(L"Edit",NULL,WS_CHILD|WS_VISIBLE|WS_VSCROLL|ES_MULTILINE| ES_READONLY ,5,30,rect.right-10,120,hwnd,NULL,Hinstance,NULL);//创建编辑框
	SendMessage(p->hEdit,WM_SETFONT,(WPARAM)p->hFont1,0);//给编辑框设置字体
	p->hL=CreateWindow(L"SysListView32",NULL,WS_CHILD|WS_VISIBLE|LVS_REPORT|LVS_SINGLESEL|LVS_NOSORTHEADER  ,5,155, rect.right-10,rect.bottom-160,hwnd,NULL,Hinstance,NULL);//创建列表视图控件

	LVCOLUMN LV;
	LV.mask=LVCF_WIDTH|LVCF_TEXT;
	LV.pszText=L"参数";LV.cx=140;
	SendMessage(p->hL,LVM_INSERTCOLUMN,(WPARAM)0,(LPARAM)&LV);//列表视图控件添加第1列
	LV.pszText=L"值";LV.cx=240;
	SendMessage(p->hL,LVM_INSERTCOLUMN,(WPARAM)1,(LPARAM)&LV);//列表视图控件添加第2列
	LV.pszText=L"说明";LV.cx=260;
	SendMessage(p->hL,LVM_INSERTCOLUMN,(WPARAM)2,(LPARAM)&LV);//列表视图控件添加第3列
	SendMessage(p->hL,LVM_SETBKCOLOR,0,(LPARAM)color1);//设置列表视图控件背景色
	SendMessage(p->hL,LVM_SETTEXTBKCOLOR,0,(LPARAM)color1);//设置列表视图控件文本背景色
	SendMessage(p->hL,LVM_SETTEXTCOLOR,0,(LPARAM)RGB(123,36,6));//设置列表视图控件文本颜色

	FilterArray.Add((DWORD*)p);//将过滤器指针添加到数组
	p->hSampleDlg=hwnd;

	SetEvent(p->hHasCreate);//发送"样本信息窗口创建完成"信号
	
	MSG msg;
	BOOL fGotMessage;
    while ((fGotMessage = GetMessage(&msg, hwnd, 0, 0)) != 0 && fGotMessage != -1) 
    { 
        TranslateMessage(&msg); 
        DispatchMessage(&msg); 
    } 
	return 1;
}

LRESULT CALLBACK LowLevelKeyboardProc(int  nCode, WPARAM wParam, LPARAM lParam)//键盘消息钩子过程
{
    if (nCode < 0)   //不处理消息
        return CallNextHookEx(hHook, nCode, wParam, lParam); 
	KBDLLHOOKSTRUCT* p=(KBDLLHOOKSTRUCT*)lParam;
	if(wParam==WM_KEYDOWN)
	{
		if(p->vkCode==113 && p->flags==0)//如果按下F2键
		{
			for(int i=0;i<FilterArray.GetCount();i++)
			{
				CFilter* m_pCFilter=(CFilter*)FilterArray.GetAt(i);
				if(m_pCFilter!=NULL)
				{
					ShowWindow(m_pCFilter->hSampleDlg, SW_SHOWDEFAULT);//显示"样本信息窗口”
					UpdateWindow(m_pCFilter->hSampleDlg);
					SendMessage(m_pCFilter->hEdit,EM_SETSEL,0,0);//设置编辑框插入符的位置为0
				}
			}
		}
	}
	return CallNextHookEx(hHook, nCode, wParam, lParam);
}

输入引脚头文件:CInputPin.h

#ifndef  PIN_FILE
#define PIN_FILE

#include "GetSample.h"
#include "CFilter.h"

class CInputPin : public CBaseInputPin
{
    friend class CFilter;
    CFilter *pCFilter;  
public:
    CInputPin(CFilter *pFilter, HRESULT *phr, LPCWSTR pPinName);
    ~CInputPin();
	HRESULT CheckConnect(IPin *pPin);
    HRESULT CheckMediaType(const CMediaType *pmt);
    HRESULT SetMediaType(const CMediaType *pmt);
    STDMETHODIMP Receive(IMediaSample *pSample);
}; 

class CPtr//用于保存媒体类型描述字符串和格式类型的数组类
{
public:
	struct item
	{
		char* p1;
		char* p2;
		char* p3;
		char* p4;
		AM_MEDIA_TYPE* pmt;
	};
	CPtr();
	int Count;
	DWORD adres[300];
	void Add(char* pch1, char* pch2, char* pch3, char* pch4, AM_MEDIA_TYPE* pmt);
	void DeleteAll();
	item* GetAt(int i);
};

#endif //PIN_FILE

输入引脚源文件:CInputPin.cpp

#include "CInputPin.h"
#include "Commctrl.h"
#include "wchar.h"
#include "stdio.h"

CPtr::CPtr()//构造函数
{
	Count=0;
}

void CPtr::Add(char* pch1,char* pch2,char* pch3,char* pch4, AM_MEDIA_TYPE* pmt)//向数组添加项
{
	if(Count==300)
	{
		MessageBox(0,L"媒体类型数量不可大于300",0,MB_OK);return;
	}
	item* p=new item();
	p->p1=pch1;p->p2=pch2;p->p3=pch3;p->p4=pch4; p->pmt=pmt;
	adres[Count]=(DWORD)p;
	Count++;
}

void _FreeMediaType(AM_MEDIA_TYPE& mt)//释放媒体类型的格式块。
{
	if (mt.cbFormat != 0)
	{
		CoTaskMemFree((PVOID)mt.pbFormat);
		mt.cbFormat = 0;
		mt.pbFormat = NULL;
	}
	if (mt.pUnk != NULL)
	{
		mt.pUnk->Release();
		mt.pUnk = NULL;
	}
}

void _DeleteMediaType(AM_MEDIA_TYPE* pmt)//删除在堆上分配的媒体类型结构
{
	if (pmt != NULL)
	{
		_FreeMediaType(*pmt);
		CoTaskMemFree(pmt);
	}
}

void CPtr::DeleteAll()//删除数组所有项
{
	for(int i=0;i<Count;i++)
	{
		item* p=(item*)adres[i];
		delete[] p->p1;delete[] p->p2;delete[] p->p3;delete[] p->p4; _DeleteMediaType(p->pmt);//必须删除获取到的媒体类型结构,包括它的格式块
		delete p;
	}
	Count = 0;
}

CPtr::item* CPtr::GetAt(int i)//获取指定位置的项
{
	CPtr::item* p=(CPtr::item*)adres[i];
	return p;
}

CPtr ptr;//媒体类型描述字符串和格式类型的数组类对象

extern HINSTANCE Hinstance;//DLL模块句柄

BOOL Check;//判断是否已使用媒体类型初始化列表。TRUE已初始化,FALSE未初始化
UINT Timer;//计时器标识

INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);//选择媒体类型模态对话框过程函数声明

CInputPin::CInputPin(CFilter *pFilter, HRESULT *phr, LPCWSTR pPinName) : CBaseInputPin(NAME("In"), pFilter, pFilter, phr, pPinName)//输入引脚构造函数
{
    pCFilter = pFilter;
	pCFilter->sel=0;
	Check=FALSE;//将选择标记重置为FALSE
	ptr.DeleteAll();//删除数组中的所有媒体类型信息
} 

CInputPin::~CInputPin()//输入引脚析构函数
{
	ptr.DeleteAll();//删除数组中的所有媒体类型信息
}

HRESULT CInputPin::CheckConnect(IPin* pPin)
{
	HRESULT hr;
	if(ptr.Count==0)//因为CheckConnect可能多次调用,只在“媒体类型描述字符串和格式类型数组“为空时,获取与此引脚连接的输出引脚的所有允许的媒体类型
	{
		IEnumMediaTypes* pEnum = NULL;
		hr = pPin->EnumMediaTypes(&pEnum);
		if (FAILED(hr))return hr;
		AM_MEDIA_TYPE* pmt = NULL; 
		while (hr = pEnum->Next(1, &pmt, NULL), hr == S_OK)//获取与此引脚连接的输出引脚的所有允许的媒体类型
		{
			char* pMain=pCFilter->GetString(pmt->majortype);//获取主要类型字符串
			char* pSub=pCFilter->GetString(pmt->subtype);//获取子类型字符串
			char* pFormat=pCFilter->GetString(pmt->formattype);//获取格式类型字符串
			char* pFormatString=pCFilter->GetFormatString(pmt->formattype, pmt->pbFormat);//获取格式结构参数字符串
			ptr.Add(pMain, pSub, pFormat, pFormatString, pmt);//添加到“媒体类型描述字符串和格式类型数组“
		}
		pEnum->Release();Check=TRUE;//标记已选择了媒体类型
	}
    return CBasePin::CheckConnect(pPin);
}

VOID CALLBACK TimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)//计时器回调函数
{
	KillTimer(NULL,Timer);//销毁计时器
	ptr.DeleteAll();//删除数组中的所有媒体类型信息
}

HRESULT CInputPin::CheckMediaType(const CMediaType *pmt)
{
	if(ptr.Count==0)return S_FALSE;
	if(Check)
	{
		if(ptr.Count==1)//只有1个媒体类型,不显示媒体类型选择对话框
		{
			pCFilter->sel=0;//将选择索引置为选择第1项
		}
		else if(ptr.Count>1)//有1个以上的媒体类型,显示媒体类型选择对话框
		{
			DialogBoxParam(Hinstance,MAKEINTRESOURCE(IDD_DIALOG1),NULL,(DLGPROC)DialogProc,(LPARAM)pCFilter);//显示媒体类型选择模态对话框。将过滤器指针作为参数传递给对话框
		}
		Check=FALSE;//确保媒体类型选择模态对话框,只显示一次
		Timer=SetTimer(NULL,0,1000,(TIMERPROC)TimerProc);//确保1秒内,不再显示媒体类型选择对话框
	}
	CPtr::item* p=ptr.GetAt(pCFilter->sel);//获取选择的媒体类型项
	CMediaType cmt(*(p->pmt));//转换为CMediaType对象
	if(cmt.MatchesPartial(pmt))//如果选定的媒体类型与pmt匹配
	{
		return S_OK;//返回S_OK,确定连接使用的媒体类型
	}
	return S_FALSE;
} 

HRESULT CInputPin::SetMediaType(const CMediaType *pmt)
{
	WaitForSingleObject(pCFilter->hHasCreate,INFINITE);//等待样本对话框创建完成
	char* String=pCFilter->GetMediaTypeString(pmt);
	SendMessageA(pCFilter->hEdit,WM_SETTEXT,0,(LPARAM)String);//在编辑框中设置媒体类型描述文本
	delete[] String;
    return CBaseInputPin::SetMediaType(pmt);
} 

HRESULT CInputPin::Receive(IMediaSample * pSample)//接收函数
{
	DWORD T=timeGetTime()-pCFilter->StartTime;//调用时间,单位毫秒
	HRESULT hr;
	pCFilter->index++;
	BYTE* pBuffer=NULL;
	hr=pSample->GetPointer(&pBuffer);//获取样本缓冲区的指针
	long BufferSize=pSample->GetSize();//缓冲区的大小
	long Len=pSample->GetActualDataLength();//有效数据的长度
	hr=pSample->IsSyncPoint();//同步点
	
	wchar_t wch[100]=L"样本";
	wchar_t wch1[100];wchar_t wch2[100];
	wmemset(wch1,0,100);
	_itow_s(pCFilter->index,wch1,10);
	wcscat_s(wch,100,wch1);//在wch后附加字符串

	if(pCFilter->B100 && pCFilter->index>100)return S_OK;//如果限制样本数量为100个,不再获取后面的样本

	if(pCFilter->Setup==2 || (pCFilter->Setup==1 && hr==S_OK))
	{
		HANDLE hFile;
		wchar_t path[MAX_PATH];wmemset(path,0,MAX_PATH);
		wcscat_s(path,MAX_PATH,pCFilter->DirectoryName);wcscat_s(path,MAX_PATH,L"\\");
		wcscat_s(path,MAX_PATH,wch);wcscat_s(path,MAX_PATH,L".dat");
		hFile=CreateFile(path,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
		OVERLAPPED oa;
		WriteFile(hFile,pBuffer,Len,(LPDWORD)&oa,NULL);//写数据文件
		CloseHandle(hFile);
	}

	LVITEM LT;LT.mask=LVIF_TEXT;
	LT.iItem=0;LT.iSubItem=0;LT.pszText=wch;
	SendMessage(pCFilter->hL,LVM_INSERTITEM,0,(LPARAM)&LT);//列表视图添加项,文本为样本序号
	wmemset(wch1,0,20);_itow_s(T,wch1,10);LT.iSubItem=1;LT.pszText=wch1;
	SendMessage(pCFilter->hL,LVM_SETITEMTEXT,0,(LPARAM)&LT);//列表视图设置子项文本项,文本为调用时间
	LT.iSubItem=2;LT.pszText=L"产生样本时间,单位毫秒";
	SendMessage(pCFilter->hL,LVM_SETITEMTEXT,0,(LPARAM)&LT);//列表视图设置子项2文本,文本为说明

	wmemset(wch,0,100);
	wcscat_s(wch,100,L"GetSize()");//在wch后附加字符串
	LT.iItem=1;LT.iSubItem=0;LT.pszText=wch;
	SendMessage(pCFilter->hL,LVM_INSERTITEM,1,(LPARAM)&LT);//列表视图添加项,文本为GetSize()
	wmemset(wch1,0,100);_itow_s(BufferSize,wch1,10);
	LT.iSubItem=1;LT.pszText=wch1;
	SendMessage(pCFilter->hL,LVM_SETITEMTEXT,1,(LPARAM)&LT);//列表视图设置子项文本项,文本为缓冲区大小
	LT.iSubItem=2;LT.pszText=L"缓冲区大小,单位字节";
	SendMessage(pCFilter->hL,LVM_SETITEMTEXT,1,(LPARAM)&LT);//列表视图设置子项2文本,文本为说明

	wmemset(wch,0,100);
	wcscat_s(wch,100,L"GetActualDataLength()");//在wch后附加字符串
	LT.iItem=2;LT.iSubItem=0;LT.pszText=wch;
	SendMessage(pCFilter->hL,LVM_INSERTITEM,2,(LPARAM)&LT);//列表视图添加项,文本为GetActualDataLength()
	wmemset(wch1,0,100);_itow_s(Len,wch1,10);
	LT.iSubItem=1;LT.pszText=wch1;
	SendMessage(pCFilter->hL,LVM_SETITEMTEXT,2,(LPARAM)&LT);//列表视图设置子项1文本,文本为有效数据的长度
	LT.iSubItem=2;LT.pszText=L"有效数据的长度,单位字节";
	SendMessage(pCFilter->hL,LVM_SETITEMTEXT,2,(LPARAM)&LT);//列表视图设置子项2文本,文本为说明

	REFERENCE_TIME star,end;
	hr=pSample->GetTime(&star,&end);//时间戳
	wmemset(wch,0,100);
	wcscat_s(wch,100,L"GetTime()");//在wch后附加字符串
	LT.iItem=3;LT.iSubItem=0;LT.pszText=wch;
	SendMessage(pCFilter->hL,LVM_INSERTITEM,3,(LPARAM)&LT);//列表视图添加项,文本为GetTime()
	if(hr==S_OK)//如果获取时间戳成功
	{
		swprintf_s(wch1,100,L"star=%I64d,",star);
		swprintf_s(wch2,100,L"end=%I64d",end);
		wmemset(wch,0,100);
		wcscat_s(wch,100,wch1);//在wch后附加字符串
		wcscat_s(wch,100,wch2);//在wch后附加字符串
	}
	else
	{
		wmemset(wch,0,100);
		wcscat_s(wch,100,L"star=NULL,end=NULL");//在wch后附加字符串
	}
	LT.iSubItem=1;LT.pszText=wch;
	SendMessage(pCFilter->hL,LVM_SETITEMTEXT,3,(LPARAM)&LT);//列表视图设置子项1文本,文本为时间戳
	LT.iSubItem=2;LT.pszText=L"样本时间戳,单位100纳秒";
	SendMessage(pCFilter->hL,LVM_SETITEMTEXT,3,(LPARAM)&LT);//列表视图设置子项2文本,文本为说明

	hr=pSample->GetMediaTime(&star,&end);//媒体的开始和结束时间
	wmemset(wch,0,100);
	wcscat_s(wch,100,L"GetMediaTime()");//在wch后附加字符串
	LT.iItem=4;LT.iSubItem=0;LT.pszText=wch;
	SendMessage(pCFilter->hL,LVM_INSERTITEM,4,(LPARAM)&LT);//列表视图添加项,文本为GetMediaTime()
	if(hr==S_OK)//如果获取媒体成功
	{
		swprintf_s(wch1,100,L"Mstar=%I64d,",star);
		swprintf_s(wch2,100,L"Mend=%I64d",end);
		wmemset(wch,0,100);
		wcscat_s(wch,100,wch1);//在wch后附加字符串
		wcscat_s(wch,100,wch2);//在wch后附加字符串
	}
	else
	{
		wmemset(wch,0,100);
		wcscat_s(wch,100,L"Mstar=NULL,Mend=NULL");
	}
	LT.iSubItem=1;LT.pszText=wch;
	SendMessage(pCFilter->hL,LVM_SETITEMTEXT,4,(LPARAM)&LT);//列表视图设置子项1文本,文本为媒体的开始和结束时间
	LT.iSubItem=2;LT.pszText=L"媒体时间,单位音频或视频帧,或100纳秒";
	SendMessage(pCFilter->hL,LVM_SETITEMTEXT,4,(LPARAM)&LT);//列表视图设置子项2文本,文本为说明

	hr=pSample->IsDiscontinuity();//流中断
	wmemset(wch,0,100);
	wcscat_s(wch,100,L"IsDiscontinuity()");//在wch后附加字符串
	LT.iItem=5;LT.iSubItem=0;LT.pszText=wch;
	SendMessage(pCFilter->hL,LVM_INSERTITEM,5,(LPARAM)&LT);//列表视图添加项,文本为IsDiscontinuity()
	wmemset(wch,0,100);
	if(hr==S_OK)wcscat_s(wch,100,L"TRUE");//在wch后附加字符串
	else wcscat_s(wch,100,L"FALSE");//在wch后附加字符串
	LT.iSubItem=1;LT.pszText=wch;
	SendMessage(pCFilter->hL,LVM_SETITEMTEXT,5,(LPARAM)&LT);//列表视图设置子项1文本,文本为
	LT.iSubItem=2;LT.pszText=L"中断标志";
	SendMessage(pCFilter->hL,LVM_SETITEMTEXT,5,(LPARAM)&LT);//列表视图设置子项2文本,文本为说明

	hr=pSample->IsSyncPoint();//同步点
	wmemset(wch,0,100);
	wcscat_s(wch,100,L"IsSyncPoint()");//在wch后附加字符串
	LT.iItem=6;LT.iSubItem=0;LT.pszText=wch;
	SendMessage(pCFilter->hL,LVM_INSERTITEM,6,(LPARAM)&LT);//列表视图添加项,文本为IsSyncPoint()
	wmemset(wch,0,100);
	if(hr==S_OK)wcscat_s(wch,100,L"TRUE");//在wch后附加字符串
	else wcscat_s(wch,100,L"FALSE");//在wch后附加字符串
	LT.iSubItem=1;LT.pszText=wch;
	SendMessage(pCFilter->hL,LVM_SETITEMTEXT,6,(LPARAM)&LT);//列表视图设置子项1文本,文本为
	LT.iSubItem=2;LT.pszText=L"同步点标志";
	SendMessage(pCFilter->hL,LVM_SETITEMTEXT,6,(LPARAM)&LT);//列表视图设置子项2文本,文本为说明

	hr=pSample->IsPreroll();//预卷样本
	wmemset(wch,0,100);
	wcscat_s(wch,100,L"IsPreroll()");//在wch后附加字符串
	LT.iItem=7;LT.iSubItem=0;LT.pszText=wch;
	SendMessage(pCFilter->hL,LVM_INSERTITEM,7,(LPARAM)&LT);//列表视图添加项,文本为IsPreroll()
	wmemset(wch,0,100);
	if(hr==S_OK)wcscat_s(wch,100,L"TRUE");//在wch后附加字符串
	else wcscat_s(wch,100,L"FALSE");//在wch后附加字符串
	LT.iSubItem=1;LT.pszText=wch;
	SendMessage(pCFilter->hL,LVM_SETITEMTEXT,7,(LPARAM)&LT);//列表视图设置子项1文本,文本为
	LT.iSubItem=2;LT.pszText=L"预卷标志";
	SendMessage(pCFilter->hL,LVM_SETITEMTEXT,7,(LPARAM)&LT);//列表视图设置子项2文本,文本为说明

	LT.iItem=8;LT.iSubItem=0;LT.pszText=L"";
	SendMessage(pCFilter->hL,LVM_INSERTITEM,8,(LPARAM)&LT);//列表视图添加空项
	return S_OK;
}

INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)//选择媒体类型模态对话框过程函数
{
	CFilter* pF=NULL;//过滤器的指针
	HWND hList;//媒体类型列表窗口句柄
	switch(uMsg)
	{
	case WM_INITDIALOG://初始化对话框
		pF=(CFilter*)lParam;
		hList=GetDlgItem(hwndDlg,IDC_LIST1);//获取媒体类型列表窗口句柄。IDC_LIST1为列表视图控件,样式为报表样式
		SetDlgItemInt(hwndDlg,IDC_EDIT2,(UINT)pF, FALSE);//将过滤器指针值,放置在不可见编辑框中
		LVCOLUMN LV;
		LV.mask=LVCF_WIDTH|LVCF_TEXT;
		LV.pszText=L"主要类型";LV.cx=160;
		SendMessage(hList,LVM_INSERTCOLUMN,(WPARAM)0,(LPARAM)&LV);//添加媒体类型列表第1列,并指定列的宽度
		LV.pszText=L"子类型";LV.cx=160;
		SendMessage(hList,LVM_INSERTCOLUMN,(WPARAM)1,(LPARAM)&LV);//添加媒体类型列表第2列,并指定列的宽度
		LV.pszText=L"格式类型";LV.cx=160;
		SendMessage(hList,LVM_INSERTCOLUMN,(WPARAM)2,(LPARAM)&LV);//添加媒体类型列表第3列,并指定列的宽度
		ListView_SetExtendedListViewStyle(hList,LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES);//指定扩展样式为:整行选择,显示网格
		for(int i=0;i<ptr.Count;i++)//将媒体类型数组中描述字符串添加到媒体类型列表
		{
			CPtr::item* p=(CPtr::item*)ptr.adres[i];
			wchar_t wch1[100],wch2[100],wch3[100];
			MultiByteToWideChar(CP_ACP,MB_COMPOSITE,p->p1,-1,wch1,100);//将char字符串转换为宽字符串
			MultiByteToWideChar(CP_ACP,MB_COMPOSITE,p->p2,-1,wch2,100);
			MultiByteToWideChar(CP_ACP,MB_COMPOSITE,p->p3,-1,wch3,100);
			LVITEM LT;
			LT.mask=LVIF_TEXT;
			LT.iItem=i;
			LT.iSubItem=0;LT.pszText=wch1;
			SendMessage(hList,LVM_INSERTITEM,i,(LPARAM)&LT);//列表视图添加项,文本为主要类型字符串
			LT.iSubItem=1;LT.pszText=wch2;
			SendMessage(hList,LVM_SETITEMTEXT,i,(LPARAM)&LT);//列表视图设置子项1文本项,文本为子类型字符串
			LT.iSubItem=2;LT.pszText=wch3;
			SendMessage(hList,LVM_SETITEMTEXT,i,(LPARAM)&LT);//列表视图设置子项2文本,文本为格式类型字符串
		}
		ListView_SetItemState(hList, 0, LVIS_FOCUSED|LVIS_SELECTED, LVIS_FOCUSED|LVIS_SELECTED);//选中第1项
		break;
	case WM_COMMAND:
		switch (LOWORD(wParam)) 
		{
		case IDOK://按下“确定”按钮
			hList=GetDlgItem(hwndDlg,IDC_LIST1);//获取媒体类型列表窗口句柄
			pF=(CFilter*)GetDlgItemInt(hwndDlg,IDC_EDIT2,NULL,FALSE);//从隐藏的编辑控件中,获取过滤器指针
			pF->sel=ListView_GetSelectionMark(hList);//获取媒体类型列表选中项的索引
			if(pF->sel==-1)
			{
				MessageBox(0,L"必须选择连接使用的媒体类型",0,MB_OK);return FALSE; 
			}
			EndDialog(hwndDlg, 1);//终止模态对话框
			return FALSE;
		}
		break;
	case WM_NOTIFY:
		switch (((LPNMHDR)lParam)->code)
		{
		case NM_CLICK://在媒体类型列表中,单击鼠标左键
			LPNMITEMACTIVATE lpnmitem = (LPNMITEMACTIVATE) lParam;
			if(lpnmitem->iItem!=-1)//如果有选中项
			{
				CPtr::item* p=(CPtr::item*)ptr.adres[lpnmitem->iItem];//根据媒体类型列表选中项的索引,获取“媒体类型描述字符串和格式类型数组“对应的项
				SetDlgItemTextA(hwndDlg,IDC_EDIT1,p->p4);//将与选中项对应的格式类型描述字符串,设置给IDC_EDIT1编辑框
			}
			break;
		}
		break;
	}
	 return FALSE; 
}

下载本过滤器DLL

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

h3974

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值