各位大虾好:
在MFC中如何实现用鼠标拖动我已经绘制在视图上的图形? 在WM_LBUTTONDOWN和WM_LBUTTONMOVE中要做点什么?能给点代码参考吗?先谢过各位大虾了。 补充:我画在视图上的图形保存在一个结构体数组中。
在MFC中如何实现用鼠标拖动我已经绘制在视图上的图形? 在WM_LBUTTONDOWN和WM_LBUTTONMOVE中要做点什么?能给点代码参考吗?先谢过各位大虾了。 补充:我画在视图上的图形保存在一个结构体数组中。
解决方案 »
- dialog上的工具栏不可用
- VC++之删除目录中同一类型(后缀)文件??
- 如何将CString字符串快速转换为十六进制的字符串?最好是系统函数。
- 自定义窗体,添加按钮控件,无法保存控件句柄怎么回事.
- vc 6.0关联文件打开出错,可能是多次安装卸载的问题,高手帮忙解决下,谢谢
- IHTMLDocument2::execCommand(L"SaveAs",VARIANT_FALSE,vValue, &vb)第三个参数怎么设啊.
- 如何在对话条(CDialogBar)上的按钮上贴位图呢?
- 点击网页上的链接运行本地程序该如何实现?
- 关于网络爬虫的设计
- 如何安装msdn?
- 内存dc画图
- 给程序添加成员变量后,程序不能执行了?
如果在了.拖动的过程中第一步是清除图形.如果你的图形有覆盖的话,别的图形要重绘..
然后move了以后重新绘制.
我的方法是建立自己的类来完成,图形操作。
类声明:
class CMX
{
public:
void Draw ( CDC *pdc ); //绘图函数,在使用该类的OnDraw中调用
void SetRn ( CDC *pdc ); //设定区域函数,每一次绘图都要根据点的位置重新设定区域
void RtTo ( CDC *pdc, PointF orpos, PointF nwpos ); //旋转函数,点的类型、旋转机制不同算法不同
void DrTo ( CDC *pdc, PointF orpos, PointF nwpos ); //平移函数,不多说了
void OnMMv ( CDC *pdc, PointF point ); //键盘操作函数,在那里用肯定知道
void OnMUp ( CDC *pdc, PointF point );
void OnMDn ( CDC *pdc, PointF point );
CArray <PointF,PointF> m_Lst; //点集,也就是你说的数组 BOOL Sted; //区域和标志,根据区域来判断标志,由标志可以知道该类的操作
BOOL Rted; BOOL DF;
BOOL DR; Region RtRn;
Region StRn; PointF DPt;
PointF Bpt; CMX();
virtual ~CMX();
private:
};类实现:
void CMX::OnMDn(CDC *pdc, PointF point)
{
DF=TRUE;
DPt=point;
Bpt=point; Sted=FALSE;
Rted=FALSE; if(StRn.IsVisible(point.X,point.Y,NULL)){ Sted=TRUE; } if(RtRn.IsVisible(point.X,point.Y,NULL)){ Rted=TRUE; }
}void CMX::OnMUp(CDC *pdc, PointF point)
{
DF=FALSE;
IsDw=FALSE;
//这里有一个函数没写,也就是重新给点集赋值的函数,因为这里是可选的,你也可以直接在旋转或平移函数中赋值
}void CMX::OnMMv(CDC *pdc, PointF point)
{
if(DF==TRUE){ DR=TRUE; }else{ DR=FALSE; }
if(DR==TRUE && Sted==TRUE){ DrTo(pdc,Bpt,point);
Bpt=point;
}else if(DR==TRUE && Rted==TRUE){
RtTo(pdc, Dpt, point);
}
}void CMX::Draw(CDC *pdc)
{
if(Sted==FALSE && Rted==FALSE)
{
DrawNm(pdc);
SetRn(pdc); }else if(Sted==TRUE){ DrawSt(pdc);
SetRn(pdc); }else if( Rted==TRUE ){ DrawRt(pdc);
SetRn(pdc);
}
}
1,先谈谈你的那个 结构体数组,该结构体中一定要包含一个区域的值,即你的图形的所在区域。
2.当鼠标左键按下时,取得鼠标的位置,然后在结构体数组中进行搜索,该点是否在区域内,是,
说明是选中的该图形
3,在onmousemove中,改变区域的值,并重绘结构体数组中的图形。(简易采用双缓冲,否则会有闪烁的现象)。
不用你处理消息。
我的问题:
***1.我一时搞不清你说的”图形所在区域“是”CClient rect"这个吗?还是? ***2.当鼠标左键按下时,我想把DOWN的点所落在的那个图形的数组下标传到UP里,在UP里重绘这个下标的图形,不知道可否?如果可以,我实现的时候在LBUTTONDOWN里,只写了个判断点如在图形内,则把下标附给一个成员变量。然后,我运行后,一点鼠标左键,我的窗口就自动关了! 什么情况?
拖动的思路是这样的:
1.鼠标落下的时候判断在什么区域当中。 比如一个矩形区域区域里面,你要是不懂得gdi+的Region,那你就用GDI的CRgn类来建立矩形的拖动区域。我习惯将这些区域设置成全局变量,6楼的方法应该是建立局部变量来判断也是可以的。 如果鼠标落在选中区域,那么就应该将图形的选中标志Sted设置为TRUE,说明当前图形处于选中状态。
2.另外就是鼠标落下DF和鼠标拖动标志DR的判断,很明显,如果你想拖动一个图形移动,首先你要点中这个图形,这个时候DF为TRUE,在鼠标移动的时候判断DF是不是TRUE,不就可以知道鼠标是不是处于拖懂状态了么。 如果在Move中发现图形处于选中状态,同时鼠标又处于拖动状态,那么就执行图形移动操作。
就是上面move中的这段代码的意思:
if(DR==TRUE && Sted==TRUE)
{
DrTo(pdc,Bpt,point); //这里我使用的是鼠标移动前一个点Bpt,如果使用鼠标落下的点Dpt,函数里面使用的算法稍有差别。
Bpt=point;
}
3.在DrTo这个代码中我一般是通过鼠标落下的点与鼠标移动的当前点这两个点,来计算图形当前所应该在的位置。这个时候,我会绘制一个图形的虚框,就好像Word里面拖动文本框时候出现的那种;但是移动的时候我会对你说的数组中的数据进行赋值的。 而且DrTo这个函数我一般会带有返回值,也就是我在Up中所说的那样,拖动的时候不赋值,我会在Up中最后赋值给数组。如果你用GDI开发这个可以减少偏差。Up时候当然需要对鼠标的标志DF、DR置成FALSE的。说了这么多,楼主还是需要自己多动手去做啊!
我先说说我的思路。
CAD中最基本图形就是直线段和圆弧。
画图需用橡皮筋功能,这样才显得高级。
记录如下特征:直线:起点、终点
圆:圆心、半径
圆弧:圆心、半径、起点度数、终点度数。选中已画好的图形:1、鼠标点击选择,计算该点是否落在图线的垂直阴影内,
在就计算距图形的最近距离,取最近一个,
在判断是否满足设定的距离要求,满足就选中
不在就计算距端点的距离,取最近一个,
在判断是否满足设定的距离要求,满足就选中
判断鼠标是否选中一个图形其实不用算法也很容易实现的。 如果用GDI的话用CRgnCRgn hRgn; //矩形区域
pdc->BeginPath();
pdc->MoveTo(左上点);
pdc->LineTo(右上点);
pdc->LineTo(右下点);
pdc->LineTo(左下点);
pdc->LineTo(左上点);
pdc->CloseFigure();
pdc->EndPath();
hRgn.CreateFromPath(pdc);GDI+的话用Region,GDI+应该比较好用,14楼的方法如果是规则图形(圆、矩形、直线),用GDI或这算法还是很容易实现的,但是
要是没法子用方程标示的曲线,那就麻烦了,就像我下面添加的Curve曲线,你很难往上面做垂线的(当然也能,但是很复杂)。这个
时候GDI+就看出它的厉害之处了。看下面代码:
PointF PTC[10];
PTC[1]=PointF(100.0,100.0);
......
PTC[9]=PointF(100.0,100.0);GraphicsPath path;
path.AddLine(Pt1,Pt2); //向路径中添加一条直线
path.AddCurve(PTC,10); //向路径中添加一条Curve,很像是Word中的曲线Pen greenPen(Color(255,0,0,0),12); //建立一个画笔,画笔的宽度就是你要选中这条路径时,有效点距离这个路径的长度(其实是2倍)
path.Widen(&greenPen); //用画笔扩充路径
Region sctRgn(&path); //通过路径建立一个区域,由于路径被扩张了,所以这个区域的样子就好像是以前路径用了一个更粗的画笔画了一边一样。if( sctRgn.IsVisible(point.X,point.Y) = TRUE )
{
//选中了
}else{
//没有选中
}另外,使用那种工具来编应该不是大问题,看你熟悉那个了。
你需要的里面全有。仔细研究一下吧。
// CEx4ViewIMPLEMENT_DYNCREATE(CEx4View, CScrollView)BEGIN_MESSAGE_MAP(CEx4View, CScrollView)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
END_MESSAGE_MAP()// CEx4View 构造/析构CEx4View::CEx4View()
: m_pointTopLeft(0, 0), m_sizeEllipse(100, -100),
m_sizeOffset(0, 0), m_bCaptrued(FALSE)
{
// TODO: 在此处添加构造代码}CEx4View::~CEx4View()
{
}BOOL CEx4View::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: 在此处通过修改
// CREATESTRUCT cs 来修改窗口类或样式 return CScrollView::PreCreateWindow(cs);
}// CEx4View 绘制void CEx4View::OnDraw(CDC* pDC)
{
/*CEx4Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;*/ CBrush brushHatch(HS_DIAGCROSS, RGB(255, 0, 0));
CPoint point(0, 0); pDC->SelectObject(&brushHatch);
pDC->Ellipse(CRect(m_pointTopLeft, m_sizeEllipse)); pDC->SelectStockObject(BLACK_BRUSH);
pDC->Rectangle(CRect(100, -100, 200, -200)); // TODO: 在此处为本机数据添加绘制代码
}void CEx4View::OnInitialUpdate()
{
CScrollView::OnInitialUpdate(); CSize sizeTotal(800, 1050);
CSize sizePage(sizeTotal.cx/2, sizeTotal.cy/2);
CSize sizeLine(sizeTotal.cx/50, sizeTotal.cy/50); SetScrollSizes(MM_LOENGLISH, sizeTotal, sizePage, sizeLine);
}void CEx4View::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CRect rectEllipse(m_pointTopLeft, m_sizeEllipse);
CRgn circle; CClientDC dc(this);
OnPrepareDC(&dc);
dc.LPtoDP(rectEllipse);
circle.CreateEllipticRgnIndirect(rectEllipse);
if(circle.PtInRegion(point))
{
SetCapture();
m_bCaptrued = TRUE; CPoint pointTemp(m_pointTopLeft);
dc.LPtoDP(&pointTemp);
m_sizeOffset = point - pointTemp; ::SetCursor(::LoadCursor(NULL, IDC_CROSS));
}
CScrollView::OnLButtonDown(nFlags, point);
}void CEx4View::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if(m_bCaptrued)
{
ReleaseCapture();
m_bCaptrued = FALSE;
}
CScrollView::OnLButtonUp(nFlags, point);
}void CEx4View::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if (m_bCaptrued)
{
CClientDC dc(this);
OnPrepareDC(&dc); CRect rectOld(m_pointTopLeft, m_sizeEllipse);
dc.LPtoDP(rectOld);
InvalidateRect(rectOld, TRUE); m_pointTopLeft = point - m_sizeOffset;
dc.DPtoLP(&m_pointTopLeft);
CRect rectNew(m_pointTopLeft, m_sizeEllipse);
InvalidateRect(rectNew, TRUE);
}
CScrollView::OnMouseMove(nFlags, point);
}
//#include "stdafx.h"
#include "Ex4.h"#include "Ex4Doc.h"
#include "Ex4View.h"#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CEx4ViewIMPLEMENT_DYNCREATE(CEx4View, CScrollView)BEGIN_MESSAGE_MAP(CEx4View, CScrollView)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
END_MESSAGE_MAP()// CEx4View 构造/析构CEx4View::CEx4View()
: m_pointTopLeft(0, 0), m_sizeEllipse(100, -100),
m_sizeOffset(0, 0), m_bCaptrued(FALSE)
{
// TODO: 在此处添加构造代码}CEx4View::~CEx4View()
{
}BOOL CEx4View::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: 在此处通过修改
// CREATESTRUCT cs 来修改窗口类或样式 return CScrollView::PreCreateWindow(cs);
}// CEx4View 绘制void CEx4View::OnDraw(CDC* pDC)
{
/*CEx4Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;*/ CBrush brushHatch(HS_DIAGCROSS, RGB(255, 0, 0));
CPoint point(0, 0); pDC->SelectObject(&brushHatch);
pDC->Ellipse(CRect(m_pointTopLeft, m_sizeEllipse)); pDC->SelectStockObject(BLACK_BRUSH);
pDC->Rectangle(CRect(100, -100, 200, -200)); // TODO: 在此处为本机数据添加绘制代码
}void CEx4View::OnInitialUpdate()
{
CScrollView::OnInitialUpdate(); CSize sizeTotal(800, 1050);
CSize sizePage(sizeTotal.cx/2, sizeTotal.cy/2);
CSize sizeLine(sizeTotal.cx/50, sizeTotal.cy/50); SetScrollSizes(MM_LOENGLISH, sizeTotal, sizePage, sizeLine);
}
// CEx4View 诊断#ifdef _DEBUG
void CEx4View::AssertValid() const
{
CScrollView::AssertValid();
}void CEx4View::Dump(CDumpContext& dc) const
{
CScrollView::Dump(dc);
}CEx4Doc* CEx4View::GetDocument() const // 非调试版本是内联的
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CEx4Doc)));
return (CEx4Doc*)m_pDocument;
}
#endif //_DEBUG
// CEx4View 消息处理程序void CEx4View::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CRect rectEllipse(m_pointTopLeft, m_sizeEllipse);
CRgn circle; CClientDC dc(this);
OnPrepareDC(&dc);
dc.LPtoDP(rectEllipse);
circle.CreateEllipticRgnIndirect(rectEllipse);
if(circle.PtInRegion(point))
{
SetCapture();
m_bCaptrued = TRUE; CPoint pointTemp(m_pointTopLeft);
dc.LPtoDP(&pointTemp);
m_sizeOffset = point - pointTemp; ::SetCursor(::LoadCursor(NULL, IDC_CROSS));
}
CScrollView::OnLButtonDown(nFlags, point);
}void CEx4View::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if(m_bCaptrued)
{
ReleaseCapture();
m_bCaptrued = FALSE;
}
CScrollView::OnLButtonUp(nFlags, point);
}void CEx4View::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if (m_bCaptrued)
{
CClientDC dc(this);
OnPrepareDC(&dc); CRect rectOld(m_pointTopLeft, m_sizeEllipse);
dc.LPtoDP(rectOld);
InvalidateRect(rectOld, TRUE); m_pointTopLeft = point - m_sizeOffset;
dc.DPtoLP(&m_pointTopLeft);
CRect rectNew(m_pointTopLeft, m_sizeEllipse);
InvalidateRect(rectNew, TRUE);
//Invalidates the client area within the given
//rectangle by adding that rectangle to the CWnd update region. //UpdateWindow();
//Updates the client area by sending a WM_PAINT
//message if the update region is not empty. //The UpdateWindow member function sends a WM_PAINT
//message directly, bypassing the application queue.
//If the update region is empty, WM_PAINT is not sent. //Invalidate(FALSE);
// Invalidates the entire client area of CWnd.
}
CScrollView::OnMouseMove(nFlags, point);
}
//抱歉 刚才没贴好