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()函数,所以重新画了这个椭圆,因此它好象被放大缩小了似的。 我的文章写完了,还有什么不懂的地方,写信给我。在关闭这个文件之前,最好你自己再复习一下,并尝试一下其他的功能。
CRectTracker类的使用--橡皮筋窗口的更多相关文章
- CRectTracker类的使用
CRectTracker(俗称“橡皮筋”类)是一个非常有意思的类.你在Windows中经常看到这样的情况:它可以用做显示边界,你也可以扽它的八个角用来放大缩小,或做框选使用.如何通过编程来实现这种功能 ...
- MFC注册窗口类以及FindWindow按窗口类名查询(避免用#32770获取窗口句柄)
呵呵,最近在研究SendMessage函数,其中需要用到m_hWnd,之后延伸着又尝试获得窗口的句柄,于是遇到了FindWindow函数,原型如下: HWND FindWindow ( LPCSTR ...
- MFC注册窗口类以及FindWindow按窗口类名查询
很多玩游戏的人都知道一般游戏客户端程序是不允许双开的,就是说在同一游戏在启动的时候,是无法打开多个窗口.很多其他软件如酷狗播放器等也是这样.如果把打开的窗口最小化,这时重新启动程序,最小化的窗口会被显 ...
- C#通过事件跨类调用WPF主窗口中的控件
xaml.cs文件: using System; using System.Timers; using System.Windows; using System.Windows.Forms; name ...
- Win32编程:窗口类样式+窗口外观样式+窗口显示样式
1.窗口类样式WNDCLASS.style CS_VREDRAW 提供窗口位置变化事件和高度变化事件的处理程序,功能是重绘窗口 CS_HREDRAW 提供窗口位置变化事件和宽度变化事件的处理程序,功能 ...
- 窗口类(Window Class)概述
windows窗口编程(通常意义上的win32)有几个比较核心的概念:入口函数WinMain.窗口类Window Class.窗口过程.消息处理机制.通用控件.本文主要介绍窗口类的相关概念,包括: 窗 ...
- 通用窗口类 Inventory Pro 2.1.2 Demo1(下续篇 ),物品消耗扇形显示功能
本篇想总结的是Inventory Pro中通用窗口的具体实现,但还是要强调下该插件的重点还是装备系统而不是通用窗口系统,所以这里提到的通用窗口类其实是通用装备窗口类(其实该插件中也有非装备窗口比如No ...
- 通用窗口类 Inventory Pro 2.1.2 Demo1(下)
本篇想总结的是Inventory Pro中通用窗口的具体实现,但还是要强调下该插件的重点还是装备系统而不是通用窗口系统,所以这里提到的通用窗口类其实是通用装备窗口类(其实该插件中也有非装备窗口比如No ...
- 通用窗口类 Inventory Pro 2.1.2 Demo1(中)
本篇想总结的是Inventory Pro中通用窗口的具体实现,但还是要强调下该插件的重点还是装备系统而不是通用窗口系统,所以这里提到的通用窗口类其实是通用装备窗口类(其实该插件中也有非装备窗口比如No ...
随机推荐
- MapReduce调度与执行原理之任务调度(续)
前言 :本文旨在理清在Hadoop中一个MapReduce作业(Job)在提交到框架后的整个生命周期过程,权作总结和日后参考,如有问题,请不吝赐教.本文不涉及Hadoop的架构设计,如有兴趣请参考相关 ...
- hdu 1565&&hdu 1569 (最大点权独立集)
题目意思很明确就是选一些没有相连的数字,使和最大,建成二分图后求最大点权独立集,, #include<stdio.h> #include<string.h> const int ...
- block 解析 - 形参变量
block形参 之前漏了一篇block形参的介绍,这里给补上. block形参就是定义block带的参数,和函数的参数使用一样,我们可以在block随意使用修改block形参. 我们来看个例子: 我们 ...
- Image控件
前台代码: <asp:Image ID="Image1" runat="server" /> 后台代码; protected void Page_L ...
- 使用contentprovider实现的日记(转)
目录结构: MyDiaryActivity.java package com.zhang.myDiary; import com.zhang.myDiary.DiaryColumn.DiaryClmn ...
- admin嵌套在spring mvc项目里,菜单栏点击新连接每次都会重置
<ul class="treeview-menu" id="ul_schedule"> <li><a href="#&q ...
- 转:git windows中文 乱码问题解决汇总
it的Windows版本Msysgit对中文的支持不够好 .当使用时,会出现以下三种情况的中文乱码: 下面的几个文件都在git安装目录下文件夹etc内.1.ls不能显示中文目录 解决办法:在git/g ...
- The type MultipartEntity is deprecated
在HttpCient4.3之前上传文件主要使用MultipartEntity这个类,但如今这个类已经不在推荐使用了(过时了).随之替代它的类是MultipartEntityBuilder.关于Mult ...
- IOS7上呈现IOS6的水滴刷新效果
IOS7上呈现IOS6的水滴刷新效果 到了IOS7 发现自带的刷新 不再是 IOS6自带的水滴效果了 你是否怀念那IOS6的效果呢? 哈哈,于是收集各方资料,整理编写一个属于自己的水滴刷新效果 ...
- protected的一些功能
java的访问限制有private.protected.public.这里只想进一步认识一下protected. 我对protected有4个疑问: 1,在相同包中,是否可以调用其它类的protect ...