Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1676293
  • 博文数量: 585
  • 博客积分: 14610
  • 博客等级: 上将
  • 技术积分: 7402
  • 用 户 组: 普通用户
  • 注册时间: 2008-05-15 10:52
文章存档

2013年(5)

2012年(214)

2011年(56)

2010年(66)

2009年(44)

2008年(200)

分类: C/C++

2009-07-10 11:49:03

如何实现一个橡皮区矩形

RectTracker(俗称橡皮筋类)是一个非常有意思的类。你在Windows中,在桌面上用鼠标拖拽,便可以看到一个虚线的矩形框,它便是橡皮筋.它可以用做显示边界,你也可以扽它的八个角用来放大缩小,做框选使用。如何通过编程来实现这种功能呢?这就是CRectTracker类的作用;

介绍橡皮筋类前,先介绍其他两个类:
Cpoint Point类,cpoint.x   cpoint.y,作为屏幕上的坐标上的xy 轴的坐标。
CRect,既矩形类。
crect.left   crect.bottom   crect.top   crect.right
Crect::setrect(crect.left, crect.top, crect.right,crect.bottom);
CrectTracker 类成员:

数据成员:(摘自msdn 2000,省略了一些)
1.
当前橡皮筋矩形的矩形框的位置
2.
决定橡皮筋矩形的最新的长和宽
3.
橡皮筋矩形的形式 如:
CRectTracker::solidLine    用实线标记矩形框
CRectTracker::dottedLine 虚线
CRectTracker::hatchedBorder 影阴线
CRectTracker::resizeInside   改变大小的句柄在橡皮筋矩形框内部(点在橡皮筋矩形框
里面来改变大小)
CRectTracker::resizeOutside 改变大小的句柄在橡皮筋矩形框外部
CRectTracker::hatchInside 影阴线布满总个矩形框

二 成员函数:
1.void Draw( CDC* pDC ) const;
这个函数用来划矩形框的边框和内部区域。
2.void GetTrueRect( LPRECT lpTrueRect ) const;
这个函数用来换回矩形框的 矩形坐标,参数为CRECT类型,返回矩形
3.int HitTest( CPoint point ) const;
当你鼠标被按下的时候,你可以调用这个函数,它将返回鼠标点在了矩形框的什么位置:可以看出,返回值如果大于等于零则在四边形区域之内。如果小于则说明不在区域范围之内。
返回值
代表的含义
-1
点在了四边形的外部
0
左上角
1
右上角
2
右下角
3
左下角(0123顺时针转了一圈)
4
顶部
5
右部
6
底部
7
左部(还是顺时针转了一圈)
8
点在了四边形的内部,但没有击中前面的那八个点
4.BOOL SetCursor( CWnd* pWnd, UINT nHitTest ) const;
调用这个函数用来 当鼠标放在矩形框时,显示各种鼠标形象
5.BOOL Track( CWnd* pWnd, CPoint point, BOOL bAllowInvert = FALSE, CWnd* pWndClipTo = NULL );
这个函数用来显示当人们用鼠标改变矩形框大小 或 拖拽矩形框时显示矩形框动作
一般由WM_LBUTTONDOWN 消息来触发这个函数, 不需要编写MouseMove函数,矩形框它就自动的变大小了呢?这就是Track()函数的功劳,从调用它到抬起鼠标键为止,它时刻的改变四边形的大小。
6.BOOL TrackRubberBand( CWnd* pWnd, CPoint point, BOOL bAllowInvert = TRUE );
当鼠标在空区域拖拽时显示橡皮筋矩形框,让鼠标画一个橡皮筋区域,第一个参数,画橡皮筋的窗体的指针,当然是this ,第二个参数,画橡皮筋的起始点。 让我们注意第三个参数,它非常有意思。当你使用 FALSE时(TRUE 值是缺省的),你的橡皮筋只能从左上到右下的画,不允许反向。编译运行一下FALSE这个值。
特别值得注意的是:在TrackRubberBand的过程中是以右键的抬起为结束的,这其间并没有CViewMouseMove发生。这一点一定要记住!这时鼠标画过的区域已经记录在CrectTracker 类数据成员 m_rect里面了,既CrectTracker:: m_rect.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
下面是工程应用中的代码
void Cmfc02Dlg::OnLButtonDown(UINT nFlags, CPoint point)
{
//当鼠标左键按下时
CRectTracker temp;
temp.TrackRubberBand(this,point,TRUE);
temp.m_rect.NormalizeRect(); //标题化矩形
//获取选取的矩形
RECT rc;
temp.GetTrueRect(&rc);
//在选取的整个过程,CRectTracker.TrackRubberBand()是阻塞的,直到鼠标左键弹起才返回,并且接管了WM_LBUTTONUP消息
SendMessage(WM_LBUTTONUP);
CDialog::OnLButtonDown(nFlags, point);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
如果要自己实现的话,可以这样做
BOOL bDown = FALSE;
CPoint posLast, posDown;
void Cmfc02Dlg::OnLButtonDown(UINT nFlags, CPoint point)
{
bDown = TRUE;
posLast = point;
posDown = point;
CDialog::OnLButtonDown(nFlags, point);
}
void Cmfc02Dlg::OnLButtonUp(UINT nFlags, CPoint point)
{
if (bDown)
{
   bDown = FALSE;
   CClientDC   dc(this);  
   CRect   rect(posDown.x,   posDown.y,   posLast.x,   posLast.y);  
   rect.NormalizeRect();  
  dc.DrawFocusRect(rect);   //异或前面画过的矩形
}
CDialog::OnLButtonUp(nFlags, point);
}
void Cmfc02Dlg::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if (bDown)
{
   CClientDC dc(this);
  if (posLast.x != posDown.x && posLast.y != posDown.y)
   {
    CRect   rect(posDown.x,   posDown.y,   posLast.x,   posLast.y);  
    rect.NormalizeRect();
    dc.DrawFocusRect(rect);
   }
   CRect rect(posDown.x,   posDown.y,   point.x,   point.y);  
   rect.NormalizeRect();  
   dc.DrawFocusRect(rect);  
     
  posLast   =   point;  
}
CDialog::OnMouseMove(nFlags, point);
}

/////////////////////////////////////////////////////////


    CRectTracker是一个很有用的类,可以通过调用CRectTracker::TrackRubberBand 响应WM_LBUTTONDOWN消息来创建一个橡皮区矩形。

下例表明使用CRectTracker移动和重置视窗中的蓝色椭圆的大小是很容易的事情。

首先,在文件档中声明一个CRectTracker数据成员:
class CSampleView : Public CView
{
 …
 public :
 CrectTracker m_tracker
 …
}
其次,在文档类的构造函数中初始化CRectTracker 对象:
CSampleDoc:: CSampleDOC ()
{
 //Initialize tracker position, size and style.
 m_tracker.m_rect.SetRect (0, 0, 10, 10)
 m_tracker.m_nStyle=CRectTracker:: resizeInside | CRectTracker ::dottedLine

}


然后,在OnDraw函数中画椭圆和踪迹矩形:
void CSampleView:: OnDraw (CDC* pDC)
{
 CSampleDoc* pDoc=GetDocument ()
 ASSERT_VALID (pDoc)

 //Select blue brush into device context.

 CBrush brush (RGB (0, 0, 255))
 CBrush* pOldBrush=pDC->SelectObject (&brush)

 //draw ellipse in tracking rectangle.

 Crect rcEllipse

 pDoc->m_tracker.GetTrueRect (rcEllipse)
//GetTrueRect(&rect)得到CRectTracker中的m_rect的大小,将其传递给rect;

 pDC->Ellipse (rcEllipse)

 //Draw tracking rectangle.

 pDoc->m_tracker.Draw (pDC)

 //Select blue brush out of device context.

 pDC->Selectobject (pOldBrush)
}
最后,使用ClassWizard处理WM_LBUTTONDOWN消息,并增加下述代码。该段代码根据鼠标击键情况可以拖放、移动或者重置椭圆的大小。
void CSampleView::OnLButtonDown (UINT nFlags, CPoint point)
{
 //Get pointer to document.
 CSampleDoc* pDoc=GetDocument ()
 ASSERT_VALID (pDoc)

 //If clicked on ellipse, drag or resize it.Otherwise create a
 //rubber-band rectangle nd create a new ellipse.

 BOOL bResult=pDoc->m_tracker.HitTest (point)!= CRectTracker::hitNothing


 //Tracker rectangle changed so update views.

 if (bResult)
 {
   pDoc->m_tracker.Track (this,point,TRue)
   pDoc->SetModifiedFlag ()
   pDoc->UpdateAllViews (NULL)
 }
 else
   pDoc->m-tracker.TrackRubberBand(this,point,TRUE)
 CView:: onLButtonDown (nFlags,point)
}
阅读(910) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~