本文配套源码下载
CRectTracker(俗称“橡皮筋”类)是一个非常有意思的类。你在Windows中经常看到这样的情况:它可以用做显示边界,你也可以扽它的八个角用来放大缩小,或做框选使用。如何通过编程来实现这种功能呢?这就是CRectTracker类的作用;
(框选) (显示边界并可以缩放)
你打开上面的那个工程文件,编译运行一下。你将看到CRectTracker的几种功能;
下面让我们来从头做一个新的工程文件,来慢慢掌握它的功能吧。
建立一个单文档的工程文件,将其命名为Rect。单击finish完成工程的建立;先编译一下,来第一次生成obj文件吧,在它生成的过程中,我们继续往下讲解;
第一步:
在CRectDoc类中生成一个公有的数据成员:m_rectTracker;之所以设成公有,因为要在View中调用它。接着我们来初始化它,在CRectDoc::CrectDoc构造函数中:
CRectDoc::CRectDoc()
{ // TODO: add one-time construction code here
m_rectTracker.m_rect.SetRect(0,0,100,100);
m_rectTracker.m_nStyle=CRectTracker::resizeInside|CRectTracker::dottedLine;
}
其中: m_rect是CRectTracker中用来控制四边形的大小位置的数据成员, SetRect使用的是View的坐标; m_nStyle是CRectTracker的类型,其中:CRectTracker::resizeInside和CRectTracker::resizeOutside是说明在m_rect的内部还是外部画区域(它们是互异的),CrectTrakcer::dottedLine是用点划线来画四边形的区域边界。 其他的值还有: CRectTracker::solidLine:用来画实线边界;(和dottedLine是互异的) CRectTracker::hatchedBorder:边界带抛面线; CRectTracker::hatchInside:内部带抛面线; 你可以运行前面的例子,上述参数都有使用。你也可以在第二步中逐一使用它们来加深理解它们各自的含义;
第二步:
接着我门在视图中画一个蓝色的椭圆; 在CRectView的OnDraw中继续我们的工作:
void CRectView::OnDraw(CDC* pDC)
{
CRectDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
CBrush brush(RGB(0,0,255));//生成蓝色的画刷;
CBrush *oldBrush=pDC->SelectObject(&brush);//将画刷选进dc;
CRect rect;
//GetTrueRect(&rect)得到CRectTracker中的m_rect的大小,将其传递给rect;
pDoc->m_rectTracker.GetTrueRect(&rect);
pDC->Ellipse (rect);//画椭圆;
//Draw tracking rectangle.
pDoc->m_rectTracker.Draw(pDC);//这句画才真正的将这个四边形画出来;
//Select blue brush out of device context.
pDC->SelectObject (oldBrush);//恢复原来的画刷;
}
注释已经在程序里了,不用再多说,编译一下。一个椭圆外带四边形边界(点划线),且四边形的四周有八个黑点;这就是CRectTracker.,你现在可以改变一下m_nStyle试试看各参数的含义;
第三步:如何象例子中的那样随着鼠标的移动自动在椭圆的周围改变光标呢?很简单只要将下面的代码加入到CRectView::OnSetCursor()就可以了:它调用了CRectTracker中的SetCursor()函数:
BOOL CRectView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{ // TODO: Add your message handler code here and/or call default
CRectDoc* pDoc = GetDocument();
if (pWnd == this && pDoc->m_rectTracker.SetCursor(this, nHitTest))
return TRUE;
return CView::OnSetCursor(pWnd, nHitTest, message);
}
编译运行一下,鼠标变化了。 第四步:我们再做另一个用于鼠标的CRectTracker类。它的作用是在鼠标按下以后可以显示虚线的选择框: 先让我们看看效果:
在CRectView中的加入如下代码:
void CRectView::OnLButtonDown(UINT nFlags, CPoint point)
{
CRectTracker temp;
temp.TrackRubberBand(this,point,TRUE);
temp.m_rect.NormalizeRect();//正规化;
CView::OnLButtonDown(nFlags, point);
}
编译运行,当你按下鼠标并拖动,你将看到效果了。
我们如何让鼠标画一个“橡皮筋”区域呢? 在CRectTracker类中的成员函数就是:TrackRubberBand(this,point,TRUE); 注意其中的三个参数:
第一个参数,画“橡皮筋”的窗体的指针,当然是this
第二个参数,画“橡皮筋”的起始点。
让我们注意第三个参数,它非常有意思。当你使用FALSE时(TRUE 值是缺省的),你的“橡皮筋”只能从左上到右下的画,不允许反向。编译运行一下FALSE这个值。
特别值得注意的是:在TrackRubberBand的过程中是以右键的抬起为结束的,这其间并没有CView的MouseMove发生。这一点一定要记住!这时鼠标画过的区域已经记录在temp的m_rect 中了,你可以根据它进行后续的判断工作。至于下面的正规化语句函数的作用与CRect中的正规化函数的作用一致:使四边形的四个角的坐标符合右大于左,底大于顶的坐标值。它主要是为了防止你使用TrackRubberBand 的FALSE参数而引起的可能出现的错误。