您的位置:首页 > 其它

使用CRectTracker类进行对象动态定位(一)

2013-11-19 14:01 232 查看
内容提要

使用VC,VB,Delphi等可视化工具进行程序设计的时候用的最多的可能就是控件的拾取,拖动以及动态定位了。例如我们可以在VC中用鼠标一次拾取数个控件,然后通过鼠标或者通过左右上下方向键进行控件的微移,从而使控件移到合适的位置,这种技术就是对象动态定位。动态定位也是交互式程序设计中最基本的操作之一。在VC中我们可以通过CRectTracker类来实现这些操作。

文章正文

一 关于中的OLE在内的应用程序。首先我们了解一下类的成员变量和成员函数

1. CRectTracker类的成员变量:

m_nHandleSize:对象的调整句柄的数目,默认情况下为8个

m_rect:对象矩形目前所占大小的位置

m_sizeMin:对象所占的矩形的最小宽度和最小高度

m_nStyle:目前对象边框和调整句柄的类型

2.CRectTracker类的成员函数

Draw(CDC* pDC):通过调用这个函数来画对象边框和调整句柄的类型。对象边框和调整句柄的具体类型由成员变量m_nStyle决定,一共有以下几种形式:

CRectTracker::solidLine 外部边界使用实线形式外部边界使用点虚线形式

CRectTracker::hatchedBorder 外部边界使用带阴影的形式调整句柄处于对象内部区域

CRectTracker::resizeOutside 调整句柄处于对象外部区域

CRectTracker::hatchInside 内部所有区域使用带阴影的形式

CRectTracker::solidLine和CRectTracker::resizeOutside不能同时共存

Track(CWnd* pWnd,CPoint point,BOOL bAllowInvert=FALSE,CWnd* pWndClipTo=NULL)

这个函数和下面的TrackRubberBand函数是整个CRectTracker类中最重要的函数,通常在消息,如果鼠标指针落在矩形的边框上,用户就可以拖动以调整矩形的大小;如果鼠标落在了矩形的内部,则用户可以拖动鼠标移动矩形。当ESC键按下时候,函数返回FALSE,函数没有起作用, 否则松开鼠标时候,返回TRUE;

那么鼠标移动时候将会产生橡皮条,这个””GetTrueRect(LPRECT lpTrueRect):获取对象所占矩形的大小,如果边框形式为CRectTracker::hatchOutside则矩形大小包括外部调整句柄的范围

Int HitTest(Cpoint point):函数返回光标在CrectTrack类中的位置,通过返回值可以确定拖动句柄的位置

CRectTracker::hitNothing –1:  没有点击任何地方

CRectTracker::hitTopLeft 0 : 点击调整标记的左上角

CRectTracker::hitTopRight 1 : 点击调整标记的右上角

CRectTracker::hitBottomRight 2: 点击调整标记的右下角

CRectTracker:hitBottomLeft 3:  点击调整标记的左下角

CRectTracker:hitTop 4 :     点击调整标记的上方

CRectTracker:hitRight 5:     点击调整标记的右方

CRectTracker:hitBottom 6:    点击调整标记的下方

CRectTracker:hitLeft 7:     点击调整标记的左方

CRectTracker:hitMiddle 8:    点击调整标记的中央

BOOL SetCursor(CWnd* pWnd,UINT nHitTest):当点击特定的位置时改变光标的形状

二 .应用示例

整个程序界面如下,我们可以通过工具栏来设置图像的边界和调整句柄的类型,同时我们可以用鼠标移动和调整整个图像,另外程序还支持用←↑→↓来微调矩形的位置,通过Shift+←↑→↓来微调矩形的大小.程序的开发步骤如下:

步骤一:使用VC的MFC AppWizard创建单文档应用程序ExamTracker,创建过程中保留默认值。

步骤二.在CExamTrackerDoc中增加两个成员变量

CRectTracker m_tracker;

BOOL m_bAllowInvert:是否允许逆向拖动,即橡皮条的落点是否小于起点。

步骤三:在CrectTrckerDemoDoc的构造函数中给m_tracker对象赋初值

m_tracker.m_rect.left = 200;

m_tracker.m_rect.top = 100;

m_tracker.m_rect.right = 301;

m_tracker.m_rect.bottom = 201;

//初始边界形式为实线

m_tracker.m_nStyle=CRectTracker::solidLine;

//允许逆向拖动

m_bAllowInvert=TRUE;

步骤四;在CExamTrackerView中编写函数OnDraw()绘制图像所示的矩形.下面的代码相信大家都看的懂.void CExamTrackerView::OnDraw(CDC* pDC){

CExamTrackerDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

CBrush* pOldBrush = NULL;

TRY

{

//用不同的画刷绘制矩形

CBrush brush1, brush2;

CRect rect;

int nWidth = pDoc->m_tracker.m_rect.Width();

int nHeight = pDoc->m_tracker.m_rect.Height();

int nSgnX = nWidth != 0 ? nWidth / abs(nWidth) : 1;

int nSgnY = nHeight != 0 ? nHeight / abs(nHeight) : 1;

pDC->SetTextAlign(TA_CENTER);//设置字体显示方式为中间对齐方式

pDC->SetBkMode(TRANSPARENT);//设置背景色为透明色

int nCenterX, nCenterY;

TEXTMETRIC tm;

pDC->GetTextMetrics(&tm);//获取字体大小

brush1.CreateSolidBrush(RGB(255, 0, 0));

pOldBrush = pDC->SelectObject(&brush1);

//设置第一个图形区域矩形的大小函数为自定义.

SetNormalRect(rect, pDoc->m_tracker.m_rect.left,

pDoc->m_tracker.m_rect.top, nWidth/2, nHeight/2);

//绘制矩形

pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATCOPY);

nCenterX = rect.left + rect.Width()/2;

nCenterY = rect.top + rect.Height()/2 - tm.tmHeight/2;

     //在矩形中央显示字符1

pDC->ExtTextOut(nCenterX, nCenterY, ETO_CLIPPED, rect, _T("1"), 1, NULL);

brush2.CreateSolidBrush(RGB(0, 255, 0));

pDC->SelectObject(&brush2);

brush1.DeleteObject();

SetNormalRect(rect, pDoc->m_tracker.m_rect.left+nWidth/2,

pDoc->m_tracker.m_rect.top, (nWidth+nSgnX)/2, nHeight/2);

pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATCOPY);

nCenterX = rect.left + rect.Width()/2;

nCenterY = rect.top + rect.Height()/2 - tm.tmHeight/2;

pDC->ExtTextOut(nCenterX, nCenterY, ETO_CLIPPED, rect, _T("2"), 1, NULL);

brush1.CreateSolidBrush(RGB(0, 0, 255));

pDC->SelectObject(&brush1);

brush2.DeleteObject();

SetNormalRect(rect, pDoc->m_tracker.m_rect.left,

pDoc->m_tracker.m_rect.top+nHeight/2, nWidth/2, (nHeight+nSgnY)/2);

pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATCOPY);

nCenterX = rect.left + rect.Width()/2;

nCenterY = rect.top + rect.Height()/2 - tm.tmHeight/2;

pDC->ExtTextOut(nCenterX, nCenterY, ETO_CLIPPED, rect, _T("3"), 1, NULL);

brush2.CreateSolidBrush(RGB(192, 192, 192));

pDC->SelectObject(&brush2);

brush1.DeleteObject();

SetNormalRect(rect, pDoc->m_tracker.m_rect.left+nWidth/2,

pDoc->m_tracker.m_rect.top+nHeight/2,

(nWidth+nSgnX)/2, (nHeight+nSgnY)/2);

pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATCOPY);

nCenterX = rect.left + rect.Width()/2;

nCenterY = rect.top + rect.Height()/2 - tm.tmHeight/2;

pDC->ExtTextOut(nCenterX, nCenterY, ETO_CLIPPED, rect, _T("4"), 1, NULL);

// cleanup DC

if (pOldBrush != NULL)

pDC->SelectObject(pOldBrush);

brush2.DeleteObject();

//这一行代码是必不可少的,通过它可以绘制限定形式的图形区域的外部边界和内部区域.

pDoc->m_tracker.Draw(pDC);

}

CATCH_ALL(e)

{

if (pOldBrush != NULL)

pDC->SelectObject(pOldBrush);

}

END_CATCH_ALL

}

在程序中用到了自定义的全局函数static void SetNormalRect(CRect& rect, int left, int top, int width, int height),函数用来设置矩形的大小,同时对矩形进行相应的校正.这种校正一般在逆向拖动时候需要,作用相当于CRect::NormalizeRect().函数定义如下:

static void SetNormalRect(CRect& rect, int left, int top, int width, int height)

{

rect.left = left;

rect.top = top;

rect.right = left + width;

rect.bottom = top + height;

int nTemp;

if (rect.left > rect.right)

{

nTemp = rect.left;

rect.left = rect.right;

rect.right = nTemp;

}

if (rect.top > rect.bottom)

{

nTemp = rect.top;

rect.top = rect.bottom;

rect.bottom = nTemp;

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: