10.19
这里我写好了界面,但我不知道8.2节具体是做什么工作的,所以我跳过了
8.2,首先创建一个最简单的媒体播放器。
8.3 我所做的工作步骤是:
1:给打开按钮添加了事件响应函数
2:在BOOL CMediaPlayerApp::InitInstance()里添加了//初始化COM
CoInitialize(NULL);
3:我将code里的打开的事件响应函数的代码复制到我了我的工程里面。
#if 1
CString strFilter = _T("AVI File (*.avi) | *.avi|");
strFilter += "MPEG File (*.mpg; *.mpeg) | *.mpg; *.mpeg|";
strFilter += "MP3 File (*.mp3) | *.mp3|";
strFilter += "WMA File (*.wma) | *.wma|";
strFilter += "All File (*.*) | *.*|";
#else
CString strFilter = _T("AVI File (*.avi)|*.avi|MPEG File (*.mpg)|*.mpg|MP3 File (*.mp3)|*.mp3|All Files (*.*)|*.*||");
#endif
CFileDialog dlg(TRUE, NULL, NULL, OFN_PATHMUSTEXIST|OFN_HIDEREADONLY, strFilter, this);
if (dlg.DoModal() == IDOK)
{
m_sourceFile = dlg.GetPathName();
m_mediaFileName =GetFileTitleFromFileName(m_sourceFile,1);
CreateGraph();
}
这里有几个问题,1:这里和书中的代码不一样。
2:编译一样有下面的错误
mediaplayerdlg.cpp(172) : error C2065: 'm_sourceFile' : undeclared identifier
mediaplayerdlg.cpp(173) : error C2065: 'm_mediaFileName' : undeclared identifier
mediaplayerdlg.cpp(173) : error C3861: 'GetFileTitleFromFileName': identifier not found
mediaplayerdlg.cpp(175) : error C3861: 'CreateGraph': identifier not found
第一二个错误好解决,我的解决方法是。m_sourceFile m_mediaFileName 实际上是CMediaPlayerDlg类的两个成员变量,加进去就可以。
public:
CString m_sourceFile; // m_sourceFile 表示的是媒体的路径
CString m_mediaFileName; // m_mediaFileName 表示是的媒体的文件名。
GetFileTitleFromFileName 完成的功能是从路径中获取多媒体文件的名称。这个函数在MSDN没有找到, 我姑计是作者自己写的一个函数。
CreateGraph 完成的功能是创建链表,连接滤波器。这个函数在MSDN没有找到,我姑计是作者自己写的一个函数。
基于此,我是这样办的。
首先处理GetFileTitleFromFileName 我在MediaPlayerDlg.h : 头文件里添加了代码
public:
CString GetFileTitleFromFileName(CString FileName, BOOL Ext);
然后在MediaPlayerDlg.cpp文件里添加了这个函数的实现。
CString CMediaPlayerDlg::GetFileTitleFromFileName(CString FileName, BOOL Ext)
{
int Where;
Where = FileName.ReverseFind('\\');
if (Where == -1)
Where = FileName.ReverseFind('/');
CString FileTitle = FileName.Right(FileName.GetLength() - 1 - Where);
if (!Ext)
{
int Which = FileTitle.ReverseFind('.');
if (Which != -1)
FileTitle = FileTitle.Left(Which);
}
return FileTitle;
} // 我记得应该有三个地方要改的,可是我找不到地方,这里我就不管了,反正编译只有一个错误了。
接着处理CreateGraph :
我按照我先前的做法void CreateGraph(); void DestroyGraph(); 两个函数,可是我却发现了好多的错误。我都快晕了。
mediaplayerdlg.cpp(204) : error C2065: 'm_pFilterGraph' : undeclared identifier
mediaplayerdlg.cpp(204) : error C2061: syntax error : identifier 'CDXGraph'
mediaplayerdlg.cpp(205) : error C2227: left of '->Create' must point to class/struct/union/generic type type is ''unknown-type''
mediaplayerdlg.cpp(210) : error C2227: left of '->RenderFile' must point to class/struct/union/generic type type is ''unknown-type''
mediaplayerdlg.cpp(217) : error C2227: left of '->SetDisplayWindow' must point to class/struct/union/generic type type is ''unknown-type''
mediaplayerdlg.cpp(217) : error C2065: 'm_videoWindow' : undeclared identifier
mediaplayerdlg.cpp(217) : error C2228: left of '.GetSafeHwnd' must have class/struct/union
type is ''unknown-type''
mediaplayerdlg.cpp(219) : error C2227: left of '->SetNotifyWindow' must point to class/struct/union/generic type type is ''unknown-type''
mediaplayerdlg.cpp(221) : error C2227: left of '->Pause' must point to class/struct/union/generic type type is ''unknown-type''
mediaplayerdlg.cpp(231) : error C2227: left of '->Stop' must point to class/struct/union/generic type type is ''unknown-type''
mediaplayerdlg.cpp(232) : error C2227: left of '->SetNotifyWindow' must point to class/struct/union/generic type type is ''unknown-type''
mediaplayerdlg.cpp(234) : error C2541: 'delete' : cannot delete objects that are not pointers
我觉得我应该是没有添加CDXGraph这个类,所以我加了上去。并在CMediaPlayerDlg 类的头文件里加了#include "CDXGraph.h" 还是有很多错误,没办法,还得一个一个。
经过纠结 我只是没有添加几个变量,添加一下就可以了,CStatic m_videoWindow; CDXGraph *m_pFilterGraph; # pragma comment (lib , "strmiids.lib") 加了这里基本上就没有错了,呵呵,
4:接着我给PLAY按钮增加响应函数。并添加代码。
if (m_pFilterGraph)
{
SetWindowText(_T("1倍速播放") + m_mediaFileName);
m_pFilterGraph->Run();
//m_volume = m_pFilterGraph->GetAudioVolume();
//m_sliderAudio.SetPos(m_volume);
//m_volume = 100;
m_pFilterGraph->ChangeAudioVolume(m_volume);
m_sliderVolume.SetPos(m_volume);
if (m_playerTimer == 0)
{
m_playerTimer = SetTimer(SLIDER_TIMER, 100, NULL);
} // 在这里我把这部代码注释,发可以放了,
}
但是有小问题,1:图像初始化的时候不显示在图像控件上。
2:视频很小。
实然,我感觉这个错误是我在生成窗口的时间,点一个叫什么框架的东西,于是,我打算重来一遍。
如果设置是
结果是这个窗口在桌面的左顶上角,且停在最小化状态。
如果选择是这样的。
这时编译窗口显示正常,且开始显示在中间。
如果不要thick frame 选项,结果跟第二个是一样的。
综上,我选择只要MAX BOX MIN BOX两个选择。(下面的工程设计都是这样的,希望不会错。) 这里我再时间去纠结代码。
经过我再一次实验,发现不是我刚刚发现的错误。现象依旧,怎么办,我还没有吃饭!!!。
10.20.2011
继续昨天的工作 , 我又发现,很可能跟位图和图像控件有关系,于是,我去找找线索。
找了没有线索。
我突然发现是不是有一个函数可以将坐标进行转换的。
public:
afx_msg BOOL OnEraseBkgnd(CDC* pDC); 于是我找到了它,现在试一下。
唉也不是,
于是我只能接着往前走了,不管这个问题。上面的代码我没有注释,因为好像对程序没有什么影响。
昨天有一个问题就是在按键PLAY里面有一段代码不知道是什么意思 。我这里把它加进去,
终于找到视频显示在顶端的原因了。
m_videoWindow 是图像控件变量,我没有将它和控件相关联,而仅仅是添加这个成员变量。唉控件变量。
m_sliderPlayer m_sliderVolume 这两个也是控件变量。
当我加进play按钮代码发现了很多问题。比如在对话框初始化的时候,有这么些代码是我没有注意到的。
// TODO: Add extra initialization here
m_pFilterGraph = NULL;
m_sliderPlayer.SetRange(0, 1000);
m_sliderPlayer.SetPos(0);
m_sliderVolume.SetRange(50,100);
m_sliderVolume.SetPos(50);
m_volume = 100;
这应该很重要。另外我给函数添加了两个消息。一个是WM_TIMER消息,另一个是WM_HSCROLL 消息。完成滚动条滚动时控制的命令。
接下来,给STOP按钮添加命令响应消息。 添加下面的代码
if (m_pFilterGraph != NULL)
{
m_pFilterGraph->Stop();
}
给暂停添加命令响应消息。添加下面的代码。
if (m_pFilterGraph != NULL)
{
m_pFilterGraph->Pause();
}
给退出添加命令响应消息。添加下面的代码。
OnBnClickedButtonStop();
CoUninitialize();
CDialog::OnOK();
给抓图添加命令响应消息。添加下面的代码。
static int c = 0;
TCHAR szFilename[MAX_PATH];
DWORD dwPathLen = 0;
if((dwPathLen = ::GetModuleFileName(::AfxGetInstanceHandle(),szFilename, MAX_PATH ))== 0)
{
return;
}
for( int i=dwPathLen-1; i>=0; i--)
{
if(('\\' == szFilename[i]) || ('/' == szFilename[i]))
{
break;
} else {
szFilename[i] = '\0';
}
}
CString str;
str.Format(_T("%s"),szFilename);
CString strTemp;
strTemp.Format(_T("%d"),c);
str += strTemp + _T(".bmp");
c++;
TCHAR *p=str.GetBuffer(str.GetLength());
str.ReleaseBuffer();
if (m_pFilterGraph != NULL)
{
if (m_pFilterGraph->SnapshotBitmap(p))
{
}else
MessageBox(_T("抓图失败!"));
}
这里我注意到,图片被保存到工程目录下,。但当我抓图完成后。播放器界面就会显示最开始的位图,只有当窗口重绘时才会显示动态的影像。这里应该是要对图像进行窗口重绘。这个工作我打算最后做。这里在书的P328面有说明 ,不全是我先前想的那样。这里提供了另一种方法。 当然,在窗口切换时还是会有不能正常显示的现象。
至此,我已经完成了一个小小的视频播放器了。
接着完成P320D面以后的工作。
捕获媒体播放的消息和各种事件,向窗口发送通知。
这里按照书上做没有错。
接着升级我的播放器。
为了在视频中显示窗口,单击鼠标右键激活菜单,需要我们重载窗口消息捕获处理函数PreTranslateMessage .
CToolTipCtrl m_tooltip 我不知道这是一个什么控件类型。我只能COPY
接着完成书中的内容,就可以实现一个播放器的功能了。