MFC动态画圆

MFC动态画圆,第1张

相关代码如下:

// 先在类中定义三个变量

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_pointOrix - m_radius, m_pointOriy - m_radius, m_pointOrix + m_radius, m_pointOriy + 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(pointx - m_pointOrix), 2) + pow(float(pointy - m_pointOriy), 2));

Invalidate();

}

}

void Cdemo98View::OnLButtonUp(UINT nFlags, CPoint point)

{

// 计算当前点距离中心点距离也就是半径 

m_radius = sqrt(pow(float(pointx - m_pointOrix), 2) + pow(float(pointy - m_pointOriy), 2));

m_painting = false;

Invalidate();

}

运行结果:

以下方法可在MFC和控制台中都可以实现:

1HDC hdc = GetDC(HWND hWnd); 获得设备上下文的客户区一个指定的窗口或整个屏幕

eg:如果是在窗口类中可以:

HDC hdc = GetDC(this->m_hWnd);

2在窗口区画点。

SetPixel(

hdc,

x, // 横坐标

y , // 纵坐标

RGB(100,100,100)); //点的颜色。

3 画线

MoveToEx(

HDC hdc,

int X, // 横坐标

int Y, // 纵坐标

LPPOINT lpPoint //保存先前的点的位置,在这里你可以直接写NULL

)

LineTo(

HDC hdc, // device context handle

int nXEnd, // x-coordinate of line's ending point

int nYEnd // y-coordinate of line's ending point

);

4画圆

函数

Ellipse(

HDC hdc, // handle to device context

int nLeftRect, // x-coord of bounding rectangle's upper-left corner

int nTopRect, // y-coord of bounding rectangle's upper-left corner

int nRightRect, // x-coord of bounding rectangle's lower-right corner

int nBottomRect // y-coord of bounding rectangle's lower-right corner

);

eg :Ellipse(hdc,0,0,100,100);

所谓的动态画线,画矩形,画椭圆的本质就是在于消隐问题的解决以及对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); //获取设备句柄

dcSetROP2(R2_NOT);//此为关键

dcSetROP2(R2_NOT);//所绘制的图形并没有消失,所以可以验证下面的连续两次颜色取反不是在一次相应中完成

//SetRop2 Specifies the new drawing mode(MSDN)

//R2_NOT Pixel is the inverse of the screen color(MSDN)

//即:该函数用来定义绘制的颜色,而该参数则将颜色设置为原屏幕颜色的反色

//这样,如果连续绘制两次的话,就可以恢复原来屏幕的颜色了(如下)

//但是,这里的连续两次绘制却不是在一次消息响应中完成的

//而是在第一次拖动响应的绘制可以显示(也就是看到的),第二次拖动绘制实现擦出(也就看不到了)

dcSelectStockObject(NULL_BRUSH);//不使用画刷

if(TRUE==m_startRect) //根据是否有单击判断是否可以画矩形

{

switch(m_drawType)

{

case 1://Rectangle

::SetCursor(m_HCross);

dcRectangle(CRect(m_startPoint,m_OldPoint));

dcRectangle(CRect(m_startPoint,point));

m_OldPoint=point;

break;

case 2: //Line

::SetCursor(m_HCross);

//擦去上一次绘制的临时线

dcMoveTo(m_startPoint);

dcLineTo(m_OldPoint);

//绘制这一次的临时线

dcMoveTo(m_startPoint);

dcLineTo(point);

//将临时线的终点复制给m_OldPoint,

//使其在消息循环的过程中将该值传递到

//擦去上一次画线的过程中,以便擦去上一次所画的线

m_OldPoint=point;

break;

case 3: //Circle

::SetCursor(m_HCross);

//擦去上一次绘制的临时圆

//设定该圆的y坐标,因为要保证两点的x之差等于y之差

m_OldPointy=m_OldPointx-m_startPointx+m_startPointy;

dcEllipse(CRect(m_startPoint,m_OldPoint));

//绘制临时圆

pointy=pointx-m_startPointx+m_startPointy;

dcEllipse(CRect(m_startPoint,point));

m_OldPoint=point;

break;

case 4: //Ellipse

::SetCursor(m_HCross);

dcEllipse(CRect(m_startPoint,m_OldPoint));

dcEllipse(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);//获取设备句柄

// dcSetROP2(R2_NOT); //在MouseMove消息响应中使用过该函数了,所以在这里再一次使用会使得其恢复为屏幕的颜色

dcSelectStockObject(NULL_BRUSH); //设置画刷为空画刷

switch(m_drawType)

{

case 1: //Retangle

//利用当前画刷绘制矩形,内部由当前空画刷(NULL_BRUSH)填充。

//擦去MouseMove消息响应中的临时矩形

dcRectangle(CRect(m_startPoint,m_OldPoint));

//绘制固定矩形

dcRectangle(CRect(m_startPoint,point));

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

break;

case 2: //Line

//擦去MouseMove消息响应中绘制的最后一次临时线

dcMoveTo(m_startPoint);

dcLineTo(m_OldPoint);

//绘制固定线

dcMoveTo(m_startPoint);

dcLineTo(point);

break;

case 3: //Circle

dcEllipse(CRect(m_startPoint,m_OldPoint));

dcEllipse(CRect(m_startPoint,point));

break;

case 4: //Ellipse

dcEllipse(CRect(m_startPoint,m_OldPoint));

dcEllipse(CRect(m_startPoint,point));

break;

case 5: //Dot

dcSetPixel(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;

}

以上为自己根据实际编程练习和对博文的学习所领悟到的,如果有哪里理解的不对,还望大家指正,谢谢哈!(代码没有问题,可以正常运行。)

注:代码的排版,我多次修改,并确保整齐,但是一旦我发表后,代码的排版就会发生改变,有几行代码就会变得不规则。

MFC里面画点是dcpixel(point)

//这里的point是你设置ClickButtonDown或者ClickButtonUp里面返回的CPoint类型的值,如果是画线的话,调用moveto()函数到直线的起点,然后lineto函数到终点

;如果你要画圆的话用Ellipse()函数,ellipse(CRect());

CRect是一个类型的变量,你需要用两个点来构造一个CRect

CRect rc ;

CStatic pPic = (CStatic)GetDlgItem(IDC_STATIC_Pic);

pPic->GetClientRect(&rc);//获得控件客户区大小

CDC pDC = pPic->GetDC();//获取绘图DC

int cx=rcright;

int cy=rcbottom;

pDC->SetMapMode(MM_ANISOTROPIC);//X=Y  

pDC->SetWindowExt(cx,cy); //设置窗口坐标系的大小

pDC->SetViewportExt(cx,cy);//定义输出视口,X向右,Y向上 |_

pDC->SetViewportOrg(m_movePointx,m_movePointy);//设置坐标原点  左下为圆点        注:我的这个坐标好像是我移动时候的标记点,你把这个设为你自己的固定点就行。

CPen pen(PS_SOLID, 1, RGB(255,0,255));

pDC->SelectObject(pen);

pDC->SelectStockObject(NULL_BRUSH);

pDC->Ellipse(&rect);        // 这个就是画圆了 其实是椭圆  只要把参数设置为正方形 就是圆了

CPen penSide(PS_SOLID, 1, RGB(255,0,0));

pDC->SelectObject(penSide);

pDC->Ellipse(&rctSide);

//删除画笔

penDeleteObject();

penSideDeleteObject();

ReleaseDC(pDC);

可以调用API的AngleArc()函数,或者CDC::AngleArc()函数

以API的AngleArc为例:

//函数原型

BOOL AngleArc(

HDC hdc, // handle to device context

int X, // x-coordinate of circle's center

int Y, // y-coordinate of circle's center

DWORD dwRadius, // circle's radius

FLOAT eStartAngle, // arc's start angle

FLOAT eSweepAngle // arc's sweep angle

);

//具体使用:如圆心(20,20),半径15,从pi/到pi/2。

AngleArc(hdc,20,20,15,pi,-pi/2);//eSweepAngle是相对起始角度计算的角度值

可以用CRgn,创建一个环形区域,然后dcFillRgn进行填充

画圆程序源代码:

import javaawt;

import javaawtevent;

public class DrawOval extends JFramwe{

public DrawOval()

{

super(画圆);

setBounds(0,0,100,100);

setVisible(true);

}

public void paint(Graphics g)

{

gsetColor(Colorred);//画红圆

gdrawOval(0,0,100,100);//在50,50处画一个半径为50的圆

}

public static void main(String[] args)

{

DrawOval do=new DrawOval();

}

}

以上就是关于MFC动态画圆全部的内容,包括:MFC动态画圆、VC6.0下如何实现圆弧插补、MFC编程ellipse()怎么画圆等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/10109115.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-05
下一篇 2023-05-05

发表评论

登录后才能评论

评论列表(0条)

保存