内容提要 使用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; } }  
说明:本教程来源互联网或网友上传或出版商,仅为学习研究或媒体推广,wanshiok.com不保证资料的完整性。
|