CRectTracker类的使用--橡皮筋窗口

CRectTracker(俗称“橡皮筋”类)是一个非常有意思的类。你在Windows中经常看到这样的情况:它可以用做显示边界,你也可以扽它的八个角用来放大缩小,或做框选使用。如何通过编程来实现这种功能呢?这就是CRectTracker类的作用;
             

(框选)                         (显示边界并可以缩放)

你打开上面的那个工程文件,编译运行一下。你将看到CRectTracker的几种功能;

下面让我们来从头做一个新的工程文件,来慢慢掌握它的功能吧。

建立一个单文档的工程文件,将其命名为Rect。单击finish完成工程的建立;先编译一下,来第一次生成obj文件吧,在它生成的过程中,我们继续往下讲解;

第一步:

在CRectDoc类中生成一个公有的数据成员:m_rectTracker;之所以设成公有,因为要在View中调用它。接着我们来初始化它,在CRectDoc::CrectDoc构造函数中:

1.CRectDoc::CRectDoc()

2.// TODO: add one-time construction code here

3.m_rectTracker.m_rect.SetRect(0,0,100,100);

4.m_rectTracker.m_nStyle=CRectTracker

5.::resizeInside|CRectTracker::dottedLine;

6.}

其中: 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中继续我们的工作:

01.void CRectView::OnDraw(CDC* pDC)

02.{

03.CRectDoc* pDoc = GetDocument();

04.ASSERT_VALID(pDoc);

05.// TODO: add draw code for native data here

06.CBrush brush(RGB(0,0,255));//生成蓝色的画刷;

07.CBrush  *oldBrush=pDC->SelectObject(&brush);//将画刷选进dc;

08.CRect rect;

09.//GetTrueRect(&rect)得到CRectTracker中的m_rect的大小,将其传递给rect;

10.pDoc->m_rectTracker.GetTrueRect(&rect);

11.pDC->Ellipse (rect);//画椭圆;

12.//Draw tracking rectangle.

13.pDoc->m_rectTracker.Draw(pDC);//这句画才真正的将这个四边形画出来;

14.//Select blue brush out of device context.

15.pDC->SelectObject (oldBrush);//恢复原来的画刷;

16.}

注释已经在程序里了,不用再多说,编译一下。一个椭圆外带四边形边界(点划线),且四边形的四周有八个黑点;这就是CRectTracker.,你现在可以改变一下m_nStyle试试看各参数的含义;

第三步:如何象例子中的那样随着鼠标的移动自动在椭圆的周围改变光标呢?很简单只要将下面的代码加入到CRectView::OnSetCursor()就可以了:它调用了CRectTracker中的SetCursor()函数:

1.BOOL CRectView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)

2.// TODO: Add your message handler code here and/or call default

3.CRectDoc* pDoc  = GetDocument();

4.if (pWnd == this && pDoc->m_rectTracker.SetCursor(this, nHitTest))

5.return TRUE;

6.return CView::OnSetCursor(pWnd, nHitTest, message);

7.}

编译运行一下,鼠标变化了。 第四步:我们再做另一个用于鼠标的CRectTracker类。它的作用是在鼠标按下以后可以显示虚线的选择框: 先让我们看看效果:

在CRectView中的加入如下代码:

1.void CRectView::OnLButtonDown(UINT nFlags, CPoint point)

2.{

3.CRectTracker temp;

4.temp.TrackRubberBand(this,point,TRUE);

5.temp.m_rect.NormalizeRect();//正规化;

6.CView::OnLButtonDown(nFlags, point);

7.}

编译运行,当你按下鼠标并拖动,你将看到效果了。 
我们如何让鼠标画一个“橡皮筋”区域呢? 在CRectTracker类中的成员函数就是:TrackRubberBand(this,point,TRUE); 注意其中的三个参数:

第一个参数,画“橡皮筋”的窗体的指针,当然是this

第二个参数,画“橡皮筋”的起始点。

让我们注意第三个参数,它非常有意思。当你使用 FALSE时(TRUE 值是缺省的),你的“橡皮筋”只能从左上到右下的画,不允许反向。编译运行一下FALSE这个值。

特别值得注意的是:在TrackRubberBand的过程中是以右键的抬起为结束的,这其间并没有CView的MouseMove发生。这一点一定要记住!这时鼠标画过的区域已经记录在temp的m_rect 中了,你可以根据它进行后续的判断工作。至于下面的正规化语句函数的作用与CRect中的正规化函数的作用一致:使四边形的四个角的坐标符合右大于左,底大于顶的坐标值。它主要是为了防止你使用TrackRubberBand 的FALSE参数而引起的可能出现的错误。

第五步:

让我们回到那个蓝色的椭圆,在开始新的步骤之前,首先来介绍一下HitTest(CPoint point)的功能:当你鼠标被按下的时候,你可以调用这个函数,它将返回鼠标点在了四边形的什么位置:


返回值


代表的含义


-1


点在了四边形的外部


0


左上角


1


右上角


2


右下角


3


左下角(0,1,2,3顺时针转了一圈)


4


顶部


5


右部


6


底部


7


左部(还是顺时针转了一圈)


8


点在了四边形的内部,但没有击中前面的那八个点

可以看出,返回值如果大于等于零则在四边形区域之内。如果小于则说明不在区域范围之内。因此我们需要加一个公有的成员函数:BOOL bDraw;为了方便起见,我把它加到CRectView中,(你也许会说,为什么不加到doc中,我也知道这有勃编程的原理,反正我高兴就得,都说C++给人了很大的自由度,所以你也别限制我)。先把它初始化为FALSE,表示不画边界,当TRUE时,表示要画边界。 定义:

01.class CRectView : public CView

02.{

03.…………

04.public:

05.BOOL bDraw;

06.…….

07.}

08.初始化:

09.CRectView::CRectView()

10.{

11.// TODO: add construction  code here

12.bDraw=FALSE;

13.}

14.将OnDraw改一下,加一句话:

15.void CRectView::OnDraw(CDC* pDC)

16.{

17.CRectDoc* pDoc = GetDocument();

18.ASSERT_VALID(pDoc);

19.// TODO: add draw code for  native data here

20.CBrush brush(RGB(0,0,255));//生成蓝色的画刷;

21.CBrush  *oldBrush=pDC->SelectObject(&brush);//将画刷选进dc;

22.CRect  rect;

23.pDoc->m_rectTracker.GetTrueRect (&rect);

24.//GetTrueRect(&rect)可以得到CRectTracker中的m_rect的大小,将其传递给rect;

25.if(bDraw) //*************新加的语句***************

26.pDC->Ellipse (rect);//画椭圆;

27.//Draw tracking rectangle.

28.pDoc->m_rectTracker.Draw (pDC);//***这句画才真正的将这个四边形画出来;***

29.//Select blue brush out  of device context.

30.pDC->SelectObject (oldBrush);//恢复原来的画刷;

31.}

32.编译运行一下,椭圆的边界没有了。

33.好了,预备知识讲完了,让我们来完成这个程序吧:

34.void CRectView::OnLButtonDown(UINT nFlags, CPoint point)

35.{

36.// TODO: Add your message  handler code here and/or call default

37.int nIn; //定义一个鼠标的点击值;

38.nIn=GetDocument()->m_rectTracker.HitTest(point); //看看点到了哪了

39.if(nIn<0)  //不在四边形区域内;

40.{

41.CRectTracker  temp;

42.temp.TrackRubberBand(this,point,TRUE);

43.temp.m_rect.NormalizeRect();

44.CRectTracker interRect;

45.//在建立一个CRectTracker;用于记录鼠标与椭圆的交集。

46.if(interRect.m_rect.IntersectRect(temp.m_rect,GetDocument()->m_rectTracker.m_rect))

47.bDraw=TRUE; //如果有交集,则画四边形的边界,说明选择了椭圆

48.else   bDraw=FALSE;

49.Invalidate(); //引起OnDraw函数的发生;

50.}

51.else

52.//在四边形区域内:

53.{

54.CClientDC dc(this);

55.GetDocument()->m_rectTracker.Draw(&dc);

56.GetDocument()->m_rectTracker.Track(this,point,TRUE);

57.// Track()是CRectTracker中最富魅力的函数。它时时的改变调用者的m_rect;

58.bDraw=TRUE;

59.Invalidate();

60.}

61.CView::OnLButtonDown(nFlags, point);

62.}

你也许会问,为什么我没有编写MouseMove函数,它就自动的变大小了呢?这就是Track()函数的功劳,从调用它到抬起鼠标键为止,它时刻的改变m_rectTracker的四边形的大小。然后由于我们使用了Invalidate()函数,所以重新画了这个椭圆,因此它好象被放大缩小了似的。 我的文章写完了,还有什么不懂的地方,写信给我。在关闭这个文件之前,最好你自己再复习一下,并尝试一下其他的功能。

时间: 2024-09-20 11:42:47

CRectTracker类的使用--橡皮筋窗口的相关文章

CRectTracker类的使用

本文配套源码下载 CRectTracker(俗称"橡皮筋"类)是一个非常有意思的类.你在Windows中经常看到这样的情况:它可以用做显示边界,你也可以扽它的八个角用来放大缩小,或做框选使用.如何通过编程来实现这种功能呢?这就是CRectTracker类的作用: (框选) (显示边界并可以缩放) 你打开上面的那个工程文件,编译运行一下.你将看到CRectTracker的几种功能: 下面让我们来从头做一个新的工程文件,来慢慢掌握它的功能吧. 建立一个单文档的工程文件,将其命名为Rect.

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

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

QQ静态截图完善实现之改造CRectTracker类

由于前次写的代码过于仓促(相关文章参见:"QQ 静态截图程序模拟实现"),还没仔细修改就投稿了,在这里向大家表示道歉,可能你觉得这种程序不值的一看,但我本着精益求精的态度,还是把它完善了一下,更重要的是深入了解CRectTracer类的内部机制,以能更灵活和使用该类 ,在此我把MFC的CRectTracker类源码,提取出来做了小小的改造,有兴趣的朋友还可能更深入的增加更 多的功能. 本文主要讲述三个问题: 程序中操作提示窗口文本更新闪烁问题: 程序在调整截取矩形大小和位置时,主窗口收

请问如何在一个新的类里操作Form1窗口的控件

问题描述 请问如何在一个新的类里操作Form1窗口的控件用Form1Formone=newForm1();么?用这个我点不出控件该怎么调用 解决方案 解决方案二:把form1里面的控件的modifer属性改为public解决方案三:使用构造函数将Form1传入这个类就可以对Form1进行操作了.解决方案四:Application["Form1"].Controls["控件名"]解决方案五:你的新类如果和你得应用程序不在同一个项目,要添加本项目的引用或通过反射调用解决

MyEclipse中各个类及包资源管理窗口最大化和最小化图标不管用

问题描述 在包资源管理窗口和结果窗口中以及每个打开的类都有最大化,最小化和关闭的快捷图标,可是今天打开机器后,单击这此图标却不管用.怎么回事,只有当双击时,该窗口会成为最大化. 解决方案 解决方案二:机器温度过高,一般是硬盘的问题.

编写一个类Spy++的搜索窗口程序

大家都用过Vc自代的工具Spy++,它可以通过鼠标来捕捉窗口,得到窗口的信息. 在MSDN里面找到了一个相关的API:RealChildWindowFromPoint: HWND RealChildWindowFromPoint( HWND hwndParent, // handle to window POINT ptParentClientCoords // client coordinates ); The RealChildWindowFromPoint function retriev

请教怎么在类中调用主窗口中的控件?

问题描述 主窗体控件不是静态的,要通过对象调用,可是主窗体对象只在程序开始实例一个.那只能建个函数传过去了?好不舒服..有没有简洁点的方法啊?? 解决方案 解决方案二:别直接调用,可以通过委托或者方法去控制解决方案三:引用1楼bdmh的回复: 别直接调用,可以通过委托或者方法去控制 什么意思?能具体点嘛?解决方案四:其实你这个...我很无解,不管你怎么调..你都要获取这个对象才能调用吧?就算用委托,也要在主窗体先实例化一个拥有委托的对象吧?..没有对象..飞起来调==?..还是我能力有限...解

MFC中CWnd类及其派生类对话框、消息处理、窗口操作

http://hi.baidu.com/xiaorida21/blog/item/8d8eb77a22eedee52e73b39e.html CWnd类 我们在屏幕上看到的所有对象都和窗口有关,它们或者派生于CWnd,属继承关系,如对话框.工具栏.状态栏.子控件:或者被CWnd合成,属服务员与服务对象关系,如图标.菜单.显示设备. CWnd类封装的窗口操作主要包含窗口的创建和销毁.操作窗口风格.操作窗口状态.窗口子类化.获取指定窗口等. 当然,CWnd还实现了其他功能: 1.绘制窗口 GetDC

class-怎么查看windows已经注册好的窗口类?

问题描述 怎么查看windows已经注册好的窗口类? 想使用windows已经注册好的窗口类,但不知道有哪些,也不知道名字.怎么才可以显示出来呢? 解决方案 VC++中为什么要注册窗口类注册窗口类注册窗口类 解决方案二: 请问什么是windows已经注册好的窗口类 解决方案三: 注册窗口类以后同一类窗口都用一套WindowProc.有统一的行为.以后不用每个窗口都实现一次了. 在我们构造一个窗口类结构后,我们需要将这个类结构指针加入到system atom table 即SAT中,这样系统就可以