MFC绘图_拉框控制放大缩小

首先,这个功能类似各种软件中点击鼠标拉框来实现这个范围内放大或缩小的控制,效果图如下:


图为”拉框“之后效果为图放大。
这里给出实现代码:
(1)先给出”橡皮条“效果的拉框:

在OnLButtonDown中写入

case 5:  
//放大、缩小、漫游操作,这里用case5来代表进行这几种才做,下同。
{
startPt=endPt=point1;
nDownNum=1;
}
在OnMouseMove中写入

if(nDownNum)
//这部分代码接上之前给出的代码用
{
CDC *pDC = GetDC();
pDC->SetROP2(R2_NOTXORPEN);
CRect rect(startPt,endPt);
pDC->Rectangle(rect);
CRect rect2(startPt,point);
pDC->Rectangle(rect2);
endPt = point;
ReleaseDC(pDC);
}
(2)实现放大缩小的实际代码:

void C画板程序View::calculateScale()
{
CRect viewRect;
this->GetClientRect(&viewRect);
if(viewRect.right - viewRect.left>100 || viewRect.top-viewRect.bottom>100)
{
// 地图区与视口的横向之比 
float scaleX =float (viewRect.Width()-20)/float(mapDrawRect.xMax - mapDrawRect.xMin);
//地图区与视口的纵向之比
float scaleY = float(viewRect.Height()-20)/float(mapDrawRect.yMax - mapDrawRect.yMin);
scale = min(scaleX,scaleY);
drawContext->scale = scale;
float ratioX =(float) (map->mapRect.yMax - map->mapRect.yMin)/(mapDrawRect.yMax - mapDrawRect.yMin);
float ratioY = (float)(map->mapRect.xMax-map->mapRect.xMin)/(mapDrawRect.xMax-mapDrawRect.xMin);
drawContext->ratio = min(ratioX,ratioY);;
if(drawContext->ratio<=1)
{
if(scaleX > scaleY)  
{
viewDrawRect->left = (viewRect.Width() - (mapDrawRect.xMax-mapDrawRect.xMin)*scale)/2;
viewDrawRect->top  = viewRect.top+10;
viewDrawRect->right = (viewRect.Width() + (mapDrawRect.xMax-mapDrawRect.xMin)*scale)/2; 
viewDrawRect->bottom = viewRect.bottom-10;
}
else 
{
viewDrawRect->left = viewRect.left+10;
viewDrawRect->top = (viewRect.Height() - (mapDrawRect.yMax-mapDrawRect.yMin)*scale)/2; 
viewDrawRect->right =  viewRect.right-10;
viewDrawRect->bottom = (viewRect.Height() + (mapDrawRect.yMax-mapDrawRect.yMin)*scale)/2;
}
}
drawContext->mapDrawRect = &mapDrawRect;
drawContext->viewDrawRect = viewDrawRect;   
}
}
另外在void C画板程序View::OnSize(UINT nType, int cx, int cy)中写入

{
CView::OnSize(nType, cx, cy);
this->calculateScale();
}
在OnLButtonUp中写入

CPoint ptM1,ptM2;
//将视图坐标转换为地图坐标
PVtoPM(&startPt,&ptM1,drawContext); 
PVtoPM(&endPt  ,&ptM2,drawContext);
//实现过程
mapDrawRect.xMin = min(ptM1.x,ptM2.x);
mapDrawRect.xMax = max(ptM1.x,ptM2.x);
mapDrawRect.yMin = min(ptM1.y,ptM2.y);
mapDrawRect.yMax = max(ptM1.y,ptM2.y);
this->calculateScale();
nDownNum  =0;
只样上述代码实现实际的放大,其他操作与此类似。
(3)下面给出坐标变换的代码:
由于屏幕坐标与实际坐标不一样,所以要进行坐标变换。

void C画板程序View::PVtoPM(CPoint *ptV,CPoint *ptM,DrawContext *drawContext)
{
//减去相对新视口的距离,起名有点误导,不是实际坐标位置
int mapLeft  = drawContext->mapDrawRect->xMin - drawContext->viewDrawRect->left/drawContext->scale;
int mapBottom = drawContext->mapDrawRect->yMin + drawContext->viewDrawRect->top/drawContext->scale;
ptM->x = mapLeft +ptV->x/drawContext->scale ;
ptM->y = (drawContext->viewDrawRect->Height() - ptV->y)/drawContext->scale + mapBottom; 
}
另外存储数据的时候可能会把PV-PM的数据转回-PV,代码如下:

void PMtoPV(CPoint *ptM,CPoint *ptV,DrawContext *drawContext)
{
int mapLeft  = drawContext->mapDrawRect->xMin - drawContext->viewDrawRect->left/drawContext->scale;
int mapBottom = drawContext->mapDrawRect->yMin + drawContext->viewDrawRect->top/drawContext->scale;
ptV->x =  (ptM->x - mapLeft)*(drawContext->scale);
ptV->y = drawContext->viewDrawRect->Height()  - (ptM->y - mapBottom) *drawContext->scale;  
return ;
}
(4)在状态栏显示屏幕坐标

CPoint ptM;
PVtoPM(&point,&ptM,drawContext);
CMFCStatusBar* pStatus = (CMFCStatusBar*)(AfxGetApp()->m_pMainWnd->GetDescendantWindow(ID_VIEW_STATUS_BAR));
CString tempStr;
tempStr.Format(_T("mapX: %d  mapY: %d"),ptM.x,ptM.y);
pStatus->SetPaneText(0,tempStr);









  • 3
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值