最近在编写视频播放相关的程序,在为视频播放器添加一个滚动条时出现了很多问题,滚动条实现的功能是:随着视频的播放滚动条移动显示进度;滚动条可以随意拖动以调整视频播放到感兴趣的地方,即可以快进后退。
之前我的做法是为滚动条添加一个事件处理程序,同时在定时器中不断更新滚动条位置,但是问题是视频出现跳跃重复现象,后来发现程序响应了滑动条OnNMCustomdrawProgress消息,并在此消息中又调整了视频播放的位置,因此会出现播放反复现象。同时问题是这个消息响应函数在滚动条变化时不断的调用,这样就达不到我要的点击的时候就调用的目的。
解决办法是
1、在OnNMReleasedcaptureProgress而不是OnNMCustomdrawProgress中响应进度条拖动消息。
2、在定时器中定时更新进度条位置。
3、同时重写PreTranslateMessage消息,在进度条被选中且鼠标左键按下的消息中,killtimer,然后再在鼠标左键弹起的消息响应中,settimer。
前两条都好解决,第三条解决办法如下:(以下部分为转载)
响应对某个控件的鼠标左键按下和抬起的消息函数实现 (转载)
http://hi.baidu.com/gootyking/item/7ba800e5151597394cdcaf2f
对话框上有好几个按钮,按下去要长时间后才抬起,中间要实现方法,不知道怎么实现按下抬起的消息,开始想,分别在按下和抬起的消息中响应,就得知道按的是什么控件,虽然感觉不难,找起来也不方便,结果就发现了另一种方法,我觉得更好一些。。。
重载Dialog的PreTranslateMessage函数 //这个不错哇
BOOL CTestDlgDlg::PreTranslateMessage(MSG* pMsg)
{
// TODO: Add your specialized code here and/or call the base class
if(pMsg->message == WM_LBUTTONDOWN)
{
if(WindowFromPoint(pMsg->pt) == GetDlgItem(IDC_BUTTON1))
{
// 可以做些什么
}
}
else if(pMsg->message == WM_LBUTTONUP)
{
if(WindowFromPoint(pMsg->pt) == GetDlgItem(IDC_BUTTON1))
{
//AfxMessageBox("Hello");
}
}
return CDialog::PreTranslateMessage(pMsg);
}
然后只需要把GetDlgItem(IDC_BUTTON1),中的控件名字换了,就好了。。然后在下面写实现什么的方法。
感谢原文作者,结合以上帮助,以下为我个人解决我的工程的办法,不用添加OnNMReleasedcaptureProgress,只用重写一个PreTranslateMessage函数,如下(程序在VS2008下用Opencv2.1编写):
BOOL CHumanDetectDlg::PreTranslateMessage(MSG* pMsg)
{
// TODO: 在此添加专用代码和/或调用基类
if (pMsg->message == WM_LBUTTONDOWN)
{
if (WindowFromPoint(pMsg->pt) == GetDlgItem(IDC_SLIDER))
{
KillTimer(1);
}
}
else if (pMsg->message == WM_LBUTTONUP)
{
if (WindowFromPoint(pMsg->pt) == GetDlgItem(IDC_SLIDER))
{
int nPos = Strl->GetPos();
if (nPos != FrameCount)//FrameCount为记录视频总帧数的变量,滑动条的范围就是0-FrameCount
{
cvSetCaptureProperty(m_pCapture,CV_CAP_PROP_POS_FRAMES,nPos);//设置视频
}
m_omitFps = nPos;//m_omitFps为记录视频帧数的变量,为防止定时器中的滑动条位置设置不会回退,这句必须有!!!
}
SetTimer(1,40,NULL);//视频帧率为25帧/s
}
return CDialog::PreTranslateMessage(pMsg);
}