MFC编程ellipse()怎么画圆 MFC动态画圆

作者&投稿:采科 (若有异议请与网页底部的电邮联系)
所谓的动态画线,画矩形,画椭圆的本质就是在于消隐问题的解决以及对Windows消息循环机制的理解,消隐问题:因为MFC中有一个函数SetROP2,通过将该函数的参数设置为R2—NOT(当前绘制的像素值设为屏幕像素值的反色,这里面的“屏幕”二字是指你所绘制的图形所占据的那一部分屏幕区域,即直线所占的屏幕区域就是直线所在的那一段线的区域),利用这一点通过在同一区域重复画两次便可以将该区域的形状消隐。

而Windows消息循环机制更好的体现于MouseMove消息响应中,因为要实现动态画线、画矩形这就体现在鼠标在绘图区的移动上,鼠标在绘图区移动时,产生动态的效果,也就是说在mouse 移动的过程中始终在画线、画矩形,这就要求在MouseMove消息响应中有画线、画矩形的相应函数的调用,但正是因为mouse移动的过程中画了很多的线、矩形,所以我们就要在mouse移动的过程中将之前画出的线、矩形消隐掉,才能保证实现了自己所要实现的功能——动态画线、画矩形,但又没有产生多余的线和矩形。
消隐的问题和动态画图的问题关键在于MouseMove消息响应中的函数调用的顺序:
1.首先将上次所画的图形消隐掉
2.画出临时的图形
3.消息循环的机制:循环执行上述代码(这是Windows循环的机制,不需要自己代码实现)

在最后的LButtonUp消息响应中,需要将上面的MouseMove消息响应中循环的最后一次中最后所画的临时图形消隐掉,之后根据LButtonUp消息响应中point参数画出最终的图形。综上可知:MouseMove中的代码和LButtonUp中消隐临时图形的代码所要实现的功能就是动态这一过程,而图形的最终绘制还在与LButtonUp消息响应及其point参数。
代码如下:
[cpp] view plaincopy
private:
[cpp] view plaincopy
//......
HCURSOR m_HCross;
UINT m_drawType;
CPoint m_OldPoint;
CPoint m_startPoint;
BOOL m_startRect;
[cpp] view plaincopy
CGISView::CGISView()
{
// TODO: add construction code here
//....
m_startRect=FALSE;
m_startPoint=0;
m_OldPoint=0;
m_drawType=0;
//初始化m_HCross为十字光标
m_HCross=AfxGetApp()->LoadStandardCursor(IDC_CROSS);

}
[cpp] view plaincopy
void CGISView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
m_startRect=TRUE; //鼠标左键单击,设置可以开始绘制矩形框
m_startPoint=point; //记录起始点
m_OldPoint=point;//设置老点也为起始点
//设置光标为十字光标
::SetCursor(m_HCross);

CView::OnLButtonDown(nFlags, point);
}
[cpp] view plaincopy
void CGISView::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default

CClientDC dc(this); //获取设备句柄
dc.SetROP2(R2_NOT);//此为关键
dc.SetROP2(R2_NOT);//所绘制的图形并没有消失,所以可以验证下面的连续两次颜色取反不是在一次相应中完成
//SetRop2 Specifies the new drawing mode.(MSDN)
//R2_NOT Pixel is the inverse of the screen color.(MSDN)
//即:该函数用来定义绘制的颜色,而该参数则将颜色设置为原屏幕颜色的反色
//这样,如果连续绘制两次的话,就可以恢复原来屏幕的颜色了(如下)
//但是,这里的连续两次绘制却不是在一次消息响应中完成的
//而是在第一次拖动响应的绘制可以显示(也就是看到的),第二次拖动绘制实现擦出(也就看不到了)

dc.SelectStockObject(NULL_BRUSH);//不使用画刷
if(TRUE==m_startRect) //根据是否有单击判断是否可以画矩形
{
switch(m_drawType)
{
case 1://Rectangle

::SetCursor(m_HCross);
dc.Rectangle(CRect(m_startPoint,m_OldPoint));
dc.Rectangle(CRect(m_startPoint,point));
m_OldPoint=point;

break;

case 2: //Line
::SetCursor(m_HCross);
//擦去上一次绘制的临时线
dc.MoveTo(m_startPoint);
dc.LineTo(m_OldPoint);

//绘制这一次的临时线
dc.MoveTo(m_startPoint);
dc.LineTo(point);

//将临时线的终点复制给m_OldPoint,
//使其在消息循环的过程中将该值传递到
//擦去上一次画线的过程中,以便擦去上一次所画的线
m_OldPoint=point;

break;
case 3: //Circle
::SetCursor(m_HCross);
//擦去上一次绘制的临时圆
//设定该圆的y坐标,因为要保证两点的x之差等于y之差
m_OldPoint.y=m_OldPoint.x-m_startPoint.x+m_startPoint.y;
dc.Ellipse(CRect(m_startPoint,m_OldPoint));

//绘制临时圆

point.y=point.x-m_startPoint.x+m_startPoint.y;
dc.Ellipse(CRect(m_startPoint,point));

m_OldPoint=point;
break;
case 4: //Ellipse
::SetCursor(m_HCross);

dc.Ellipse(CRect(m_startPoint,m_OldPoint));
dc.Ellipse(CRect(m_startPoint,point));
m_OldPoint=point;
break;
case 5: //Dot

break;

}
[cpp] view plaincopy
}
[cpp] view plaincopy
}
[cpp] view plaincopy
void CGISView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
m_startRect=FALSE;//重置绘制矩形框标志
::ClipCursor(NULL);//解锁光标,即将光标恢复为默认光标
//消隐最后的一个矩形
CClientDC dc(this);//获取设备句柄
// dc.SetROP2(R2_NOT); //在MouseMove消息响应中使用过该函数了,所以在这里再一次使用会使得其恢复为屏幕的颜色
dc.SelectStockObject(NULL_BRUSH); //设置画刷为空画刷
switch(m_drawType)
{
case 1: //Retangle

//利用当前画刷绘制矩形,内部由当前空画刷(NULL_BRUSH)填充。
//擦去MouseMove消息响应中的临时矩形
dc.Rectangle(CRect(m_startPoint,m_OldPoint));
//绘制固定矩形
dc.Rectangle(CRect(m_startPoint,point));

//m_drawType=0; //该行的可以使得每画一次都要选择所画的形状
break;

case 2: //Line

//擦去MouseMove消息响应中绘制的最后一次临时线
dc.MoveTo(m_startPoint);
dc.LineTo(m_OldPoint);

//绘制固定线
dc.MoveTo(m_startPoint);
dc.LineTo(point);
break;
case 3: //Circle

dc.Ellipse(CRect(m_startPoint,m_OldPoint));
dc.Ellipse(CRect(m_startPoint,point));
break;
case 4: //Ellipse

dc.Ellipse(CRect(m_startPoint,m_OldPoint));
dc.Ellipse(CRect(m_startPoint,point));
break;
case 5: //Dot
dc.SetPixel(point,RGB(0,0,0));
break;

}
CView::OnLButtonUp(nFlags, point);
}
[cpp] view plaincopy
void CGISView::OnRectangle()
{
// TODO: Add your command handler code here
m_drawType=1;//设置所画的为矩形

}

void CGISView::OnLine()
{
// TODO: Add your command handler code here
m_drawType=2;
}

void CGISView::OnEllipse()
{
// TODO: Add your command handler code here
m_drawType=4;
}

void CGISView::OnDot()
{
// TODO: Add your command handler code here
m_drawType=5;

}

void CGISView::OnCircle()
{
// TODO: Add your command handler code here
m_drawType=3;
}

以上为自己根据实际编程练习和对博文的学习所领悟到的,如果有哪里理解的不对,还望大家指正,谢谢哈!(代码没有问题,可以正常运行。)
注:代码的排版,我多次修改,并确保整齐,但是一旦我发表后,代码的排版就会发生改变,有几行代码就会变得不规则。

CDC::Ellipse
BOOL Ellipse( int x1, int y1, int x2, int y2 );

BOOL Ellipse( LPCRECT lpRect );

Return Value

Nonzero if the function is successful; otherwise 0.

Parameters

x1

Specifies the logical x-coordinate of the upper-left corner of the ellipse’s bounding rectangle.

y1

Specifies the logical y-coordinate of the upper-left corner of the ellipse’s bounding rectangle.

x2

Specifies the logical x-coordinate of the lower-right corner of the ellipse’s bounding rectangle.

y2

Specifies the logical y-coordinate of the lower-right corner of the ellipse’s bounding rectangle.

lpRect

Specifies the ellipse’s bounding rectangle. You can also pass a CRect object for this

所以,直接使用pDC->Ellipse(x1,y1,x2,y2)就可以了。
前两个参数为左上角的坐标
后两个参数为右下角的坐标

BOOL Ellipse(
int x1,
int y1,
int x2,
int y2
);
BOOL Ellipse(
LPCRECT lpRect
);
一般在OnDraw函数中有一个参数pDC,使用这个参数,pDC->Ellopse(x1,y1,x2,y2)就行了。

MFC 用Ellipse画圆如何确定圆心的位置~

你好!
x=(m_ptStar.x+m_ptEnd.x)/2
y=(m_ptStar.y+m_ptEnd.y)/2
希望对你有所帮助,望采纳。

相关代码如下:
// 先在类中定义三个变量bool m_painting;// 是否正在绘制CPoint m_pointOri;// 中心点float m_radius;// 半径Cdemo98View::Cdemo98View(){m_painting = false;m_radius = 0;}void Cdemo98View::OnDraw(CDC* pDC){Cdemo98Doc* pDoc = GetDocument();ASSERT_VALID(pDoc);if (!pDoc)return;pDC->Ellipse(m_pointOri.x - m_radius, m_pointOri.y - m_radius, m_pointOri.x + m_radius, m_pointOri.y + m_radius);}void Cdemo98View::OnLButtonDown(UINT nFlags, CPoint point){m_pointOri = point;m_radius = 0;m_painting = true;}void Cdemo98View::OnMouseMove(UINT nFlags, CPoint point){if (m_painting) {// 计算当前点距离中心点距离也就是半径 m_radius = sqrt(pow(float(point.x - m_pointOri.x), 2) + pow(float(point.y - m_pointOri.y), 2));Invalidate();}}void Cdemo98View::OnLButtonUp(UINT nFlags, CPoint point){// 计算当前点距离中心点距离也就是半径 m_radius = sqrt(pow(float(point.x - m_pointOri.x), 2) + pow(float(point.y - m_pointOri.y), 2));m_painting = false;Invalidate();}运行结果:

MATLAB求画出的两个椭圆的相交部分的面积
答:利用蒙特卡洛方法 主程序 clc;clearcir1 = [1,2,8,4,45];cir2 = [1,4,6,4,60];fcir = @(cir)ellipse1(cir(1),cir(2),[cir(3),axes2ecc(cir(3),cir(4))],cir(5));[x1,y1] = fcir(cir1);[x2,y2] = fcir(cir2);plot(x1,y1,'r-.',x2,y2,'b.')axis equa...

那位高人有cad快捷键,拜托可以发过来吗
答:ED *DDEDIT 编辑文字、标注文字、属性定义和特征控制框ES *ELLIPSE 创建椭圆EG *LENGTHEN 修改对象的长度和圆弧的包含角EX *EXTEND 延伸对象ER *LAYER 管理图层和图层特性EE *LINETYPE 加载、设置和修改线型F *FILLET 倒圆角FC *POLYGON 创建闭合的等边多段线FD *OPEN 打开现有的图形文件FE *EXPORT 以其他文件格...

cad快捷键所有的
答:acad.pgp文件的第二部分定义了命令别名。使用记事本或任何以ASCII格式保存文件的文本编辑器,用户可以编辑acad.pgp以更改现有别名或添加新的别名。要打开PGP文件,请在“工具”菜单上,单击“自定义”“编辑自定义文件”“程序员数”(acad.pgp)。此文件还可以用分号(;)引入说明文字快捷键就是指命令的别...

急求CAD快捷命令 命令缩写 越全越好
答:“左手键”快捷命令表A*ARC 创建圆弧AD*ATTEDIT改变属性信息AA*AREA计算对象或指定区域的面积和周长AG*ALIGN将对象与其他对象对齐AP*APPLOAD加载或卸载应用程序AR*ARRAY阵列AT*MATCHPROP将选定对象的特性应用到其他对象ATT*ATTDEF创建属性定义AV*DSVIEWER鸟瞰视图 B*BLOCK创建块BD*BOUNDARY从封闭区域创建面域或...

CAD快捷键
答:ELLIPSE:创建椭圆或椭圆弧 EL ERASE:从图形中删除对象 E EXPLODE:将组合对象分解为对象组件 X EXPORT:以其他文件格式保存对象 EXP EXTEND:延伸对象到另一对象 EX EXTRUDE:通过拉伸现有二维对象来创建三维原型 EXT FILLET:给对象的边加圆角 F FILTER:创建可重复使用的过滤器以便根据特性选择对象 FI GROUP:创建对象的...

CAD的命令全部有多少?
答:十、 椭圆:EL (ellipse)创造椭圆或椭圆的弧 十一、 插入块:ddinsert(insert block)插入木块或另外的图画 十二、 创建块:bmake(make block)用对话框定义木块 十三、 点:PO(point)创造点 十四、 图案填充:BH(Bhatch)填充图案 十五、 域:REG(region)从现存对象的选择设置创建...

CAD常用命令有哪些(最好是二维的)?
答:EL, *ELLIPSE(椭圆)REG, *REGION(面域)MT, *MTEXT(多行文本)T, *MTEXT(多行文本)B, *BLOCK(块定义)I, *INSERT(插入块)W, *WBLOCK(定义块文件)DIV, *DIVIDE(等分)H, *BHATCH(填充)修改命令:CO, *COPY(复制)MI, *MIRROR(镜像)AR, *ARRAY(阵列 其他命令 ADCENTER(...

GUI画图板(绘图板)设计,用Java编写程序代码!!谢谢!!
答:s=new Ellipse2D.Double(cx,cy,cd,cd); break; case 4: Path2D p=new Path2D.Double(); p.moveTo(mx,my); if(pc==1){ p.lineTo(tx, ty); } else{ p.quadTo(ox,oy,tx,ty); } s=p; break; } ts=new S(s,m.fc.getBackground(),m.bc.getBackground(),m.fillC.isSelected(),m...

如何用drawRect方法画一个实心圆
答:请参考:http://wenku.baidu.com/view/6dff062ca32d7375a41780fc.htmlpublic void paintIcon(Component c, Graphics g, int x, int y) { Graphics2D g2d = (Graphics2D)g; g2d.setColor(Color.YELLOW); //绘制圆形背景 g2d.fill(new Ellipse2D.Double(x, y,getWidth(),get...