Chinaunix首页 | 论坛 | 博客
  • 博客访问: 589247
  • 博文数量: 752
  • 博客积分: 40000
  • 博客等级: 大将
  • 技术积分: 5005
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-13 14:47
文章分类

全部博文(752)

文章存档

2011年(1)

2008年(751)

我的朋友

分类:

2008-10-13 16:48:43

浅谈在应用CRectTracker类的程序中响应WM_LBUTTONUP消息

作者:


  CRectTracker类也有人称之为“橡皮筋”类。我们可以通过Windows自带的画图板来了解这个类的作用:用“选定”功能在画图区随意选中一块儿区域,此时会出现一个由虚线和八个调整标记点组成的矩形选框,我们可通过鼠标点中矩形选框的中心移动其位置,并且能利用调整标记点来改变其大小……这个矩形选框其实就是一个“橡皮筋选框”。
  CRectTracker类的使用并不是什么新鲜的话题,然而在应用这个类的过程中,我却发现了一个小问题:我创建了一个对话框程序,希望利用CRectTracker类在对话框上画出一个“橡皮筋选框”,为了使鼠标按下并拖动鼠标的同时出现虚线的选择框,我在程序中加入了以下代码:

void CCRectTracker_DemoDlg::OnLButtonDown(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	//当鼠标左键按下时
	CRectTracker temp;
	temp.TrackRubberBand(this,point,TRUE);
	temp.m_rect.NormalizeRect();
	
	CDialog::OnLButtonDown(nFlags, point);
}

这段代码确实实现了我所期望的效果。但在程序的另一个地方:

void CCRectTracker_DemoDlg::OnLButtonUp(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	//当鼠标左键松开时
	MessageBox("鼠标左键松开","松开",NULL);
	
	CDialog::OnLButtonUp(nFlags, point);
}

  OnLButtonUp()事件丝毫不理睬我鼠标的动作——MessageBox()并没有执行。仔细一想:TrackRubberBand()是以鼠标左键的松开作为结束标志的,当WM_LBUTTONUP消息发出后,TrackRubberBand()在OnLButtonUp()事件响应前就截获了该消息,所以OnLButtonUp()事件就无法正常响应了……想到这里,脑海中也就浮现了一个解决这个小问题的办法,那就是:在TrackRubberBand()后,向程序自身发送一个自己构造的WM_LBUTTONUP消息。于是将OnLButtonDown()中的代码改写成为以下形式:

void CCRectTracker_DemoDlg::OnLButtonDown(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default

	//当鼠标左键按下时
	CRectTracker temp;
	temp.TrackRubberBand(this,point,TRUE);
	temp.m_rect.NormalizeRect();

	//自己构造的WM_LBUTTONUP消息
	this->SendMessage(WM_LBUTTONUP,NULL,NULL);

	CDialog::OnLButtonDown(nFlags, point);
}

  测试后的结果另人满意,现在我所遇到的问题迎刃而解了。在本文附带的Demo程序中,程序分别获取鼠标左键按下和松开时的坐标,然后调用修改后的OnPaint()来画出“橡皮筋矩形”,下面给出Demo中的部分关键代码:

BOOL CCRectTracker_DemoDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
{
	// TODO: Add your message handler code here and/or call default

	//////////////////////
	//改变光标的形状
	if (pWnd == this && m_rectTracker.SetCursor(this, nHitTest))
		return TRUE;
	//////////////////////
	else
		return CDialog::OnSetCursor(pWnd, nHitTest, message);
}

void CCRectTracker_DemoDlg::OnLButtonDown(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default

	///////////////////////////////////////
	//如鼠标点击位置不在选框区域内,则构造一个新选框
	Invalidate(TRUE);
	if(m_rectTracker.HitTest(point)<0)
	{
		IsLButtonDown=TRUE;
		CRectTracker temp;
		temp.TrackRubberBand(this,point,TRUE);
		temp.m_rect.NormalizeRect();
		
		//鼠标(矩形选框)起始位置
		pt_start=point;
		//鼠标(矩形选框)结束位置
		GetCursorPos(&pt_end);
		this->SendMessage(WM_LBUTTONUP,NULL,NULL);
	}
	//否则重置选框大小或位置
	else
	{
		m_rectTracker.Track(this,point,TRUE);
		m_rectTracker.m_rect.NormalizeRect();
		this->OnPaint();
	}
	///////////////////////////////////////
	
	CDialog::OnLButtonDown(nFlags, point);
}

void CCRectTracker_DemoDlg::OnLButtonUp(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default

	/////////////////////////////////
	//确保在构造一个新选框时才响应OnLButtonUp,否则在响应OnLButtonDblClk时会出现错误结果
	if(IsLButtonDown==TRUE)
	{
		//MessageBox("鼠标左键松开","松开",NULL);
		
		//由于GetCursorPos获得的pt_end是Screen坐标,故用ScreenToClient()进行转换
		rect.right=pt_end.x;
		rect.bottom=pt_end.y;
		ScreenToClient(&rect);
		pt_end.x=rect.right;
		pt_end.y=rect.bottom;
		
		//left,top,right,bottom
		m_rectTracker.m_rect.SetRect(pt_start.x,pt_start.y,pt_end.x,pt_end.y);
		m_rectTracker.m_rect.NormalizeRect();
		
		this->OnPaint();
		IsLButtonDown=FALSE;
	}
	/////////////////////////////////
	
	CDialog::OnLButtonUp(nFlags, point);
}

void CCRectTracker_DemoDlg::OnLButtonDblClk(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default

	////////////////////////////
	MessageBox("鼠标左键双击","双击",NULL);
	////////////////////////////
	
	CDialog::OnLButtonDblClk(nFlags, point);
}

由于本人水平所限,关于CRectTracker类的详细使用方法请参阅其他资料。谢谢!

附:
  以上代码在Win2000P+SP4/Win98se + VC6+SP6测试通过。
  源码可从我的个人主页下载。
  
  


--------------------next---------------------

我还没有使用,但我认为这篇文章还是很有意义的.
因为onchangedrect好像是个动态连续的过程,其实我只想获得鼠标抬起时候图形的位置. ( harrybotter 发表于 2007-9-26 15:28:00)
 
写得不错, 继续努力!!!!!!!!!!!!!!

( 井中月_VC 发表于 2007-1-29 10:01:00)
 
我对MFC知之甚少,谢指教。 ( Vegeta 发表于 2006-8-6 10:24:00)
 
并不是说你文章写的多不好,只是觉得你绕过来绕过去 看得让人头晕
1.MFC把LB_UP屏蔽掉 自然就是不想让你响应
2.m_rect在CRectTracker里为public就是要让你访问
3.还有部分诸如 onchangerect为virtual就是让你重载

MFC 就是为了不让你在外部进行苦苦的坐标记录 所以才进行封装. ( vc_mhx 发表于 2006-8-3 11:57:00)
 
是我写的这篇拙文,请教下,那像这问题怎么解决? ( Vegeta 发表于 2006-7-20 16:58:00)
 
晕死,这么好用的类被你用成这样. ( vc_mhx 发表于 2006-7-19 19:09:00)
 
.......................................................

--------------------next---------------------

阅读(394) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~