挑战高手:如何在处理doubleclick 事件的时候不处理click事件? 在程序中:单击和双击均有响应函数。但是在双击的时候,不希望单击的函数被处理,不知道如何处理? 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 可以具体说说怎么做吗?我试过用timer,没有成功 呵呵。我刚才也用了黑牛的方法试了。不行。当你点击很快的时候,第二次点击OnLButtonDown并不能响应。可能MFC已经有了一定的延时了。如果稍微慢一点,才能判断出来。怎么才能让第二次点击也被OnLButtonDown接收到呢??? 如果连续两次点击很快而单击响应函数没有执行到,那很好啊!这样的话,楼主的“但是在双击的时候,不希望单击的函数被处理”的目的就已经达到,我想楼主的目的是当双击的速度低于Windows系统双击的速度默认值(可以在控制面板的“鼠标”一项里设置),但是高于自己规定的双击速度时,单击响应函数不被执行,这样我的方法还是有用的,希望和 happyparrot(快乐鹦鹉)这样的高手讨论一下,请多多指教。 OnLButtonDown()函数保持为空, 不作任何处理。这样可以吗? 关键是OnLButtonDown()里面也会有相应的处理 To:puppet(小虎) 我已经考虑到你在OnLButtonDown()里面也会有相应的处理,不知道你试过我的方法没有. To:happyparrot(快乐鹦鹉)如果两次点击相隔时间较长(比Windows设置的双击时间还长),难道OnLButtonDown()函数还响应不到第二次点击吗?不会吧! 我想了一个办法。将鼠标点击要处理的内容做成一个函数。在OnLButtonDown中,设置定时器。在VIEW中,记录一个变量m_nCal用来计数。初始值为0比如SetTimer(1,10,NULL);定时器的间隔由你自己考虑设置。点击后,先将m_nCal置为1。然后,在OnTimer中,做m_nCal++,如果m_nCal计数到一定值,就是我们可以认为不会有双击事件发生的时间段后,就调用前面定义的那个鼠标点击处理函数。然后,在KillTimer(1),并将m_nCal=0。恢复状态。然后,响应OnLButtonDBClk事件。在该事件的开始,就判断m_nCal是否等于0,如果不是,那么显然先前响应了OnLButtonDown(好像肯定响应啊?),然后就KillTimer(1),将m_nCal=0。恢复状态。大家看看,我的思路有问题没有? 黑牛:楼主的意思,是如果双击(应该是说,比windows定义的双击还快时),他一次也不想调用OnLButtonDown中已经写的程序。你好像没弄明白。 一个完整的鼠标双击过程,系统产生了四个消息 WM_LBUTTONDOWN WM_LBUTTONUP WM_LBUTTONDBLCLK WM_LBUTTONUP能否形成双击,要看时间间隔是否在系统定义的时间间隔内两次发生点击事件可是这个时候第一组鼠标点击事件已经发出了按照常规,这个鼠标事件的响应函数可能都执行完了我们自己建立一个数据结构,来模拟消息队列,在鼠标单击和双击的响应函数当中,都向这个数据结构当中填写鼠标事件发生的位置,状态,类型(单§双击)以及时间信息。再写一个定时器,自动处理这个数据结构,检测其中相邻两次的时间间隔如果当前检测的是一个鼠标点击时间,下一个也是鼠标单击事件,则执行单击操作如果下次是一个双击事件,则屏蔽这个消息如果当前是最后一个事件,而消息时间距离当前超过了系统间隔,是单击否则等这样做会导致系统的响应延迟,(延迟时间由定时器时间和系统间隔来决定)费这样的力气值得吗? 可以用如下方法解决BOOL dbClick = FALSE;void CTestView::OnLButtonDown(UINT nFlags, CPoint point) { dbClick = FALSE; // TODO: Add your message handler code here and/or call default CView::OnLButtonDown(nFlags, point);}void CTestView::OnLButtonUp(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default if(!dbClick) SetTimer(1, GetDoubleClickTime(), NULL); CView::OnLButtonUp(nFlags, point);}void CTestView::OnLButtonDblClk(UINT nFlags, CPoint point) { dbClick = TRUE; CView::OnLButtonDblClk(nFlags, point);}void CTestView::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default KillTimer(nIDEvent); if(dbClick) MessageBox("Double clicked!"); else MessageBox("Single click!"); CView::OnTimer(nIDEvent);}如果觉得延时太大可以调用SetDoubleClickTime();将双击延时减小,缺省是500ms; 已经验证我的方法可行 代码如下:class MyMouseEvent{public: CPoint point; UINT nFlags; int nT; DWORD dwTime;};CList<MyMouseEvent*, MyMouseEvent*> mouseEvent;CString str;void CMy111View::OnDraw(CDC* pDC){ CMy111Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); static bool bStart = true; if ( bStart ) { SetTimer(100, 50, NULL); bStart = false; }; pDC->TextOut(0, 0, str); // TODO: add draw code for native data here}void CMy111View::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default MyMouseEvent * pEvent = new MyMouseEvent; pEvent->point = point; pEvent->nFlags = nFlags; pEvent->dwTime = GetTickCount(); pEvent->nT = 0; mouseEvent.AddTail(pEvent); CView::OnLButtonDown(nFlags, point);}void CMy111View::OnLButtonDblClk(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default MyMouseEvent * pEvent = new MyMouseEvent; pEvent->point = point; pEvent->nFlags = nFlags; pEvent->dwTime = GetTickCount(); pEvent->nT = 1; mouseEvent.AddTail(pEvent); CView::OnLButtonDblClk(nFlags, point);}BOOL CMy111View::DestroyWindow() { // TODO: Add your specialized code here and/or call the base class mouseEvent.RemoveAll(); KillTimer(100); return CView::DestroyWindow();} void CMy111View::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default if ( nIDEvent == 100 ) { CClientDC dc(this); DWORD curTime = GetTickCount(); int nCount = mouseEvent.GetCount(); if (1==nCount ) { // only one click, MyMouseEvent * pEvent = mouseEvent.GetHead(); if ( pEvent->nT ) { str = "double click"; delete pEvent; mouseEvent.RemoveAt(mouseEvent.GetHeadPosition()); Invalidate(); UpdateWindow(); } else if ( curTime - pEvent->dwTime > 300 ) { // expire system str = "click"; delete pEvent; mouseEvent.RemoveAt(mouseEvent.GetHeadPosition()); Invalidate(); UpdateWindow(); } // else waiting .... } else if (nCount>1 ) { MyMouseEvent * pFirst = mouseEvent.GetHead(); POSITION pos = mouseEvent.GetHeadPosition(); mouseEvent.GetNext(pos); MyMouseEvent * pSec = mouseEvent.GetNext(pos); if ( pFirst->nT ) { str = "double click"; delete pFirst; mouseEvent.RemoveAt(mouseEvent.GetHeadPosition()); Invalidate(); } else if ( pSec->nT ) { str = "double click"; delete pFirst; delete pSec; mouseEvent.RemoveAt(mouseEvent.GetHeadPosition()); mouseEvent.RemoveAt(mouseEvent.GetHeadPosition()); Invalidate(); } else { str = "click"; delete pFirst; mouseEvent.RemoveAt(mouseEvent.GetHeadPosition()); Invalidate(); }; }; }; CView::OnTimer(nIDEvent);} VC程序中调用7za.dll 解压缩 一个动态多线程的问题 DrawText中的第二个参数前面怎么加了个_ 还是双击的问题 关于VC作数据库的问题?在线等待!!! 听说MFC将被微软淘汰 如何将一个树节点作为一行显示在CListCtrl中? 关于Cancel按钮的问题 关于ADO访问大容量数据库的记录集数目获取问题 画一个80mm*60mm的编辑框 怎样在对话框上的picture control上的jpg或bmp图像上画圆或矩形? 怎么样才能在jpg或bmp照片上画图呢?有代码吗?
我试过用timer,没有成功
在OnLButtonDown中,设置定时器。在VIEW中,记录一个变量m_nCal用来计数。初始值为0
比如SetTimer(1,10,NULL);定时器的间隔由你自己考虑设置。点击后,先将m_nCal置为1。
然后,在OnTimer中,做m_nCal++,如果m_nCal计数到一定值,就是我们可以认为不会有双击事件发生的时间段后,就调用前面定义的那个鼠标点击处理函数。然后,在KillTimer(1),并将m_nCal=0。恢复状态。
然后,响应OnLButtonDBClk事件。
在该事件的开始,就判断m_nCal是否等于0,如果不是,那么显然先前响应了OnLButtonDown(好像肯定响应啊?),然后就KillTimer(1),将m_nCal=0。恢复状态。
大家看看,我的思路有问题没有?
WM_LBUTTONDOWN
WM_LBUTTONUP
WM_LBUTTONDBLCLK
WM_LBUTTONUP
能否形成双击,要看时间间隔是否在系统定义的时间间隔内两次发生点击事件
可是这个时候第一组鼠标点击事件已经发出了
按照常规,这个鼠标事件的响应函数可能都执行完了我们自己建立一个数据结构,来模拟消息队列,在鼠标单击和双击的响应函数当中,都向这个数据结构当中填写鼠标事件发生的位置,状态,类型(单§双击)以及时间信息。
再写一个定时器,自动处理这个数据结构,检测其中相邻两次的时间间隔
如果当前检测的是一个鼠标点击时间,下一个也是鼠标单击事件,则执行单击操作
如果下次是一个双击事件,则屏蔽这个消息
如果当前是最后一个事件,而消息时间距离当前超过了系统间隔,是单击否则等这样做会导致系统的响应延迟,(延迟时间由定时器时间和系统间隔来决定)费这样的力气值得吗?
BOOL dbClick = FALSE;
void CTestView::OnLButtonDown(UINT nFlags, CPoint point)
{
dbClick = FALSE;
// TODO: Add your message handler code here and/or call default
CView::OnLButtonDown(nFlags, point);
}void CTestView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if(!dbClick)
SetTimer(1, GetDoubleClickTime(), NULL); CView::OnLButtonUp(nFlags, point);
}
void CTestView::OnLButtonDblClk(UINT nFlags, CPoint point)
{
dbClick = TRUE;
CView::OnLButtonDblClk(nFlags, point);
}void CTestView::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
KillTimer(nIDEvent);
if(dbClick)
MessageBox("Double clicked!");
else
MessageBox("Single click!");
CView::OnTimer(nIDEvent);
}
如果觉得延时太大可以调用SetDoubleClickTime();将双击延时减小,缺省是500ms;
class MyMouseEvent
{
public:
CPoint point;
UINT nFlags;
int nT;
DWORD dwTime;
};CList<MyMouseEvent*, MyMouseEvent*> mouseEvent;CString str;
void CMy111View::OnDraw(CDC* pDC)
{
CMy111Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
static bool bStart = true;
if ( bStart ) {
SetTimer(100, 50, NULL);
bStart = false;
}; pDC->TextOut(0, 0, str);
// TODO: add draw code for native data here
}void CMy111View::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
MyMouseEvent * pEvent = new MyMouseEvent;
pEvent->point = point;
pEvent->nFlags = nFlags;
pEvent->dwTime = GetTickCount();
pEvent->nT = 0;
mouseEvent.AddTail(pEvent);
CView::OnLButtonDown(nFlags, point);
}void CMy111View::OnLButtonDblClk(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
MyMouseEvent * pEvent = new MyMouseEvent;
pEvent->point = point;
pEvent->nFlags = nFlags;
pEvent->dwTime = GetTickCount();
pEvent->nT = 1;
mouseEvent.AddTail(pEvent);
CView::OnLButtonDblClk(nFlags, point);
}BOOL CMy111View::DestroyWindow()
{
// TODO: Add your specialized code here and/or call the base class
mouseEvent.RemoveAll();
KillTimer(100);
return CView::DestroyWindow();
}
void CMy111View::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
if ( nIDEvent == 100 )
{
CClientDC dc(this); DWORD curTime = GetTickCount();
int nCount = mouseEvent.GetCount();
if (1==nCount )
{ // only one click,
MyMouseEvent * pEvent = mouseEvent.GetHead();
if ( pEvent->nT ) {
str = "double click";
delete pEvent;
mouseEvent.RemoveAt(mouseEvent.GetHeadPosition());
Invalidate();
UpdateWindow();
}
else if ( curTime - pEvent->dwTime > 300 )
{ // expire system
str = "click";
delete pEvent;
mouseEvent.RemoveAt(mouseEvent.GetHeadPosition());
Invalidate();
UpdateWindow();
}
// else waiting ....
}
else if (nCount>1 )
{
MyMouseEvent * pFirst = mouseEvent.GetHead();
POSITION pos = mouseEvent.GetHeadPosition();
mouseEvent.GetNext(pos);
MyMouseEvent * pSec = mouseEvent.GetNext(pos);
if ( pFirst->nT ) {
str = "double click";
delete pFirst;
mouseEvent.RemoveAt(mouseEvent.GetHeadPosition());
Invalidate();
}
else if ( pSec->nT ) {
str = "double click";
delete pFirst;
delete pSec;
mouseEvent.RemoveAt(mouseEvent.GetHeadPosition());
mouseEvent.RemoveAt(mouseEvent.GetHeadPosition());
Invalidate();
} else {
str = "click";
delete pFirst;
mouseEvent.RemoveAt(mouseEvent.GetHeadPosition());
Invalidate();
};
};
};
CView::OnTimer(nIDEvent);
}