📄 xiaoguanview.cpp
字号:
// xiaoguanView.cpp : implementation of the CXiaoguanView class
//
#include "stdafx.h"
#include "math.h"
#include "xiaoguan.h"
#include "xiaoguanDoc.h"
#include "xiaoguanView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CXiaoguanView
IMPLEMENT_DYNCREATE(CXiaoguanView, CView)
BEGIN_MESSAGE_MAP(CXiaoguanView, CView)
//{{AFX_MSG_MAP(CXiaoguanView)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_COMMAND(ID_xiaoguanLine, OnxiaoguanLine)
ON_COMMAND(ID_xiaoguanCcircle, OnxiaoguanCcircle)
ON_COMMAND(ID_BEZIER, OnBezier)
ON_COMMAND(ID_CLEAR, OnClear)
ON_COMMAND(ID_DRAWPIXEL, OnDrawpixel)
ON_COMMAND(ID_xiaoguanduobianxing, Onxiaoguanduobianxing)
ON_WM_RBUTTONDOWN()
ON_WM_RBUTTONUP()
ON_COMMAND(ID_xiaoguanEllipse, OnxiaoguanEllipse)
ON_COMMAND(ID_xiaoguanfilled, Onxiaoguanfilled)
ON_COMMAND(ID_xiaoguanColor, OnxiaoguanColor)
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CXiaoguanView construction/destruction
CXiaoguanView::CXiaoguanView()
{
// TODO: add construction code here
m_bmouseDown = false;
m_hCross = AfxGetApp()->LoadStandardCursor(IDC_CROSS);
m_hArrow = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
// m_bmouseDown=false;
m_start=true;
m_totnum=0;
m_drawpixel=false;
m_makeBezier=false;
color=RGB(255,255,0);
}
CXiaoguanView::~CXiaoguanView()
{
}
BOOL CXiaoguanView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CXiaoguanView drawing
void CXiaoguanView::OnDraw(CDC* pDC)
{
CXiaoguanDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
}
/////////////////////////////////////////////////////////////////////////////
// CXiaoguanView printing
BOOL CXiaoguanView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
void CXiaoguanView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}
void CXiaoguanView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}
/////////////////////////////////////////////////////////////////////////////
// CXiaoguanView diagnostics
#ifdef _DEBUG
void CXiaoguanView::AssertValid() const
{
CView::AssertValid();
}
void CXiaoguanView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CXiaoguanDoc* CXiaoguanView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CXiaoguanDoc)));
return (CXiaoguanDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CXiaoguanView message handlers
void CXiaoguanView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CClientDC dc(this);
if(n==5)
{
m_point[m_totnum++]=point;
}
if(m_drawpixel)
{
m_point[m_totnum++]=point;
if(m_totnum>=2)
{CClientDC dc(this);
dc.MoveTo(m_point[m_totnum-2]);
dc.LineTo(m_point[m_totnum-1]);
}
}
/*SetCapture(); // 将鼠标消息发送到视窗口
CRect rect;
GetClientRect(&rect); // 得到客户窗口的大小
ClientToScreen(&rect); // 将当前窗口坐标转换成屏幕坐标
ClipCursor(&rect); // 把鼠标限定在其参数指定的矩形区域内
SetCursor(m_hCross);*/ // 设置鼠标形状为十字形
if((n==1)|(n==2)|(n==8))
{
SetCapture(); // 将鼠标消息发送到视窗口
CRect rect;
GetClientRect(&rect); // 得到客户窗口的大小
ClientToScreen(&rect); // 将当前窗口坐标转换成屏幕坐标
ClipCursor(&rect); // 把鼠标限定在其参数指定的矩形区域内
SetCursor(m_hCross);
m_bmouseDown = true; // 鼠标左键按下
m_ptStart = point;
m_ptOld = point;
}
if(n==3)
{
if(m_start)
{
m_start=false;
A=point;
m_ptStart=point;
nCount=0;
lpPoints[nCount]=point;
nCount++;
}
else
{m_ptOld=point;
CClientDC dc(this);
dc.MoveTo(m_ptStart);
dc.LineTo(m_ptOld);
m_ptStart=point;
lpPoints[nCount]=point;
nCount++;
}
}
CView::OnLButtonDown(nFlags, point);
}
void CXiaoguanView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if (m_bmouseDown )
{
m_bmouseDown=false;
ReleaseCapture();
ClipCursor( NULL );
CClientDC dc(this);
dc.SetROP2( R2_NOT );
dc.MoveTo( m_ptStart ); //这两行代码擦除从起点(鼠标按下点)到
dc.LineTo( m_ptOld ); //上次鼠标移动到的位置之间的临时线
//dc.SetROP2( R2_COPYPEN );
//dc.MoveTo(m_ptStart);
//dc.LineTo(point);
if (n==2)
{
m_circle(m_ptStart.x,point.x,m_ptStart.y,point.y,color);
}
if (n==1)
{
dda_line(m_ptStart.x,m_ptStart.y,point.x,point.y,color);
}if (n==8)
{
m_Ellipse(m_ptStart.x,m_ptStart.y ,point.x,point.y,m_ptStart,color);
}
SetCursor(m_hArrow);
}
CView::OnLButtonUp(nFlags, point);
}
void CXiaoguanView::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if( m_bmouseDown )
{
CClientDC dc(this);
//dc.SetROP2( R2_NOT );
//dc.MoveTo( m_ptStart ); //这两行代码擦除从起点(鼠标按下点)到
//dc.LineTo( m_ptOld ); //上次鼠标移动到的位置之间的临时线
//dc.MoveTo( m_ptStart ); //这两行代码从起点到鼠标当前位置画线
// dc.LineTo( point ); //
//m_ptOld = point; //鼠标当前位置在下一次鼠标移动事件看来就是"旧位置"
}
CView::OnMouseMove(nFlags, point);
}
void CXiaoguanView::m_circle(float x1,float x2,float y1,float y2,int color)
{
float r,x=0,y,deltax,deltay,d;
r=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
y=r;
CClientDC dc(this);
dc.SetPixel(x1+x,y1+y,220);
deltax=3;deltay=2-r-r;d=1-r;
while(x<y)
{
if(d<0)
{
d+=deltax;
deltax+=2;
x++;
}
else
{
d+=(deltax+deltay);
deltax+=2;deltay+=2;
x++;y--;
}
dc.SetPixel(x1+x,y1+y,color);
dc.SetPixel(x1-x,y1-y,color);
dc.SetPixel(x1-x,y1+y,color);
dc.SetPixel(x1+x,y1-y,color);
dc.SetPixel(x1-y,y1-x,color);
dc.SetPixel(x1+y,y1+x,color);
dc.SetPixel(x1+y,y1-x,color);
dc.SetPixel(x1-y,y1+x,color);
}
}
void CXiaoguanView::dda_line(int xa,int ya,int xb,int yb,int c)
{
float delta_x, delta_y, x, y;
int dx, dy, steps, k;
dx=xb-xa;
dy=yb-ya;
if (abs(dx)>abs(dy)) steps=abs(dx);
else steps=abs (dy);
delta_x=(float)dx / (float)steps;
delta_y=(float)dy / (float)steps;
x=xa;
y=ya;
CClientDC dc(this);
dc.SetPixel(x+0.5,y+0.5,c);
for (k=1; k<=steps; k++)
{
x+=delta_x;
y+=delta_y;
dc.SetPixel(x+0.5,y+0.5,c);
}
}
/*void CXiaoguanView::Onxiaoguandraw()
{
// TODO: Add your command handler code here
}*/
void CXiaoguanView::OnxiaoguanLine()
{ AfxMessageBox("可以用你所选择的颜色画直线了");
n=1; // TODO: Add your command handler code here
}
void CXiaoguanView::OnxiaoguanCcircle()
{ AfxMessageBox("可以用你所选择的颜色画圆了");
n=2 ;// TODO: Add your command handler code here
}
void CXiaoguanView::OnBezier()
{
n=5;// TODO: Add your command handler code here
CString mes;
CClientDC dc(this);
mes.Format("一共有%d个控制点!",m_totnum);
m_drawpixel=false;
m_makeBezier=true;
dc.TextOut(400,400,mes);
AfxMessageBox("开始作Bezier曲线!");
if(m_makeBezier)
{
if(m_totnum>=2)
makeBezier();
else
AfxMessageBox("您给的控制点数量不够!");
}
}
void CXiaoguanView::OnClear()
{
n=6;// TODO: Add your command handler code here
Invalidate(TRUE);
m_totnum=0;
m_drawpixel=false;
m_makeBezier=false;
}
double CXiaoguanView::m_power(double tt, int ii)
{
double ress=1.0;
int jj=0;
for(jj=0;jj<ii;jj++)
{
ress*=tt;
}
return ress;
}
long CXiaoguanView::m_stair(int aaa)
{
int tem=1;
int dd;
int temp_aaa=aaa;
for(dd=0;dd<aaa;dd++)
{
tem*=temp_aaa;
temp_aaa--;
}
return tem;
}
int CXiaoguanView::makeBezier()
{
CClientDC dc(this);
int i=0;
double tempx=0.0;
double tempy=0.0;
CPoint cur_point;
double t=0.0;
int n=m_totnum-1;
while(t<=1)
{
tempx=0.0;
tempy=0.0;
i=0;
while(i<=n)
{
tempx+=(m_point[i].x*m_power(t,i)*m_power((1-t),(n-i))*m_Zuhe(n,i));
tempy+=(m_point[i].y*m_power(t,i)*m_power((1-t),(n-i))*m_Zuhe(n,i));
i++;
}
cur_point.x=(long)tempx;
cur_point.y=(long)tempy;
t+=0.00001;
dc.SetPixel(cur_point.x,cur_point.y,RGB(255,0,0));
}
return 0;
}
long CXiaoguanView::m_Zuhe(int nn, int ii)
{
long res;
res=m_stair(nn)/((m_stair(ii))*m_stair(nn-ii));
return(res);
}
void CXiaoguanView::OnDrawpixel()
{
// TODO: Add your command handler code here
m_drawpixel=true;
m_makeBezier=false;
AfxMessageBox("开始作控制点了!");
}
void CXiaoguanView::Onxiaoguanduobianxing()
{AfxMessageBox("可以开始用你选择的颜色画多边形了!");
n=3;
// TODO: Add your command handler code here
}
void CXiaoguanView::OnRButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if (n==3)
{
m_start=true;
ReleaseCapture();
ClipCursor( NULL );
CClientDC dc(this);
dc.MoveTo(m_ptStart);
dc.LineTo(A);
CRect rect;
}
CView::OnRButtonDown(nFlags, point);
}
void CXiaoguanView::OnRButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if(RightDown)
{
RightDown=false;
ReleaseCapture();
ClipCursor(NULL);
}
CView::OnRButtonUp(nFlags, point);
}
void CXiaoguanView::m_Ellipse(float x1, float x2, float y1, float y2,CPoint o,int color)
{
int x,y,a,b;
a=x1;
b=x2;
float d1,d2;
CClientDC dc(this);
x=0;y=b;
d1=b*b+a*a*(-b+0.25);
dc.SetPixel(x+0.5+o.x,y+0.5+o.y,255);
dc.SetPixel(-y+0.5+o.x,x+0.5+o.y,255);
dc.SetPixel(y+0.5+o.x,-x+0.5+o.y,255);
dc.SetPixel(-x+0.5+o.x,-y+0.5+o.y,255);
while (b*b*(x+1)<a*a*(y-0.5))
{
if (d1<0)
{
d1+=b*b*(2*x+3);
x++;
}
else
{
d1+=(b*b*(2*x+3)+a*a*(-2*y+2));
x++;y--;
}
dc.SetPixel(x+0.5,y+0.5,255);
}
d2=sqrt(b*(x+0.5))+sqrt(a*(y-1))-sqrt(a*b);
while(y>0)
{
if (d2<0)
{
d2+=b*b*(2*x+2)+a*a*(-2*y+3);
x++;y--;
}
else
{
d2+=a*a*(-2*y+3);
y--;
}
dc.SetPixel(x+0.5+o.x,y+0.5+o.y,255);
dc.SetPixel(-y+0.5+o.x,x+0.5+o.y,255);
dc.SetPixel(y+0.5+o.x,-x+0.5+o.y,255);
dc.SetPixel(-x+0.5+o.x,-y+0.5+o.y,255);
}
}
void CXiaoguanView::OnxiaoguanEllipse()
{
n=8;
// TODO: Add your command handler code here
}
void CXiaoguanView::FillPolygon(CPoint *lpPoints, int nCount, int nColor)
{
// 检查参数合法性
//ASSERT_VALID(pDC);
ASSERT(lpPoints);
ASSERT(nCount>2);
ASSERT(nColor>=0);
// 边结构数据类型
typedef struct Edge{
int ymax; // 边的最大y坐标
float x; // 与当前扫描线的交点x坐标
float dx; // 边所在直线斜率的倒数
struct Edge * pNext; // 指向下一条边
}Edge, * LPEdge;
int i=0,j=0,k=0;
int y0=0,y1=0; // 扫描线的最大和最小y坐标
LPEdge pAET=NULL; // 活化边表头指针
LPEdge * pET=NULL; // 边表头指针
pAET=new Edge; // 初始化表头指针,第一个元素不用
pAET->pNext=NULL;
// 获取y方向扫描线边界
y0=y1=lpPoints[0].y;
for(i=1;i<nCount;i++)
{
if(lpPoints[i].y<y0)
y0=lpPoints[i].y;
else if(lpPoints[i].y>y1)
y1=lpPoints[i].y;
}
if(y0>=y1) return;
// 初始化边表,第一个元素不用
pET=new LPEdge[y1-y0+1];
for(i=0;i<=y1-y0;i++)
{
pET[i]= new Edge;
pET[i]->pNext=NULL;
}
for(i=0;i<nCount;i++) //构造边表
{
j=(i+1)%nCount; // 组成边的下一点
if(lpPoints[i].y != lpPoints[j].y)// 如果该边不是水平的则加入边表
{
LPEdge peg; // 指向该边的指针
LPEdge ppeg; // 指向边指针的指针
// 构造边
peg =new Edge;
k=(lpPoints[i].y>lpPoints[j].y)?i:j;
peg->ymax=lpPoints[k].y; // 该边最大y坐标
k=(k==j)?i:j;
peg->x=(float)lpPoints[k].x; // 该边与扫描线焦点x坐标
if(lpPoints[i].y != lpPoints[j].y)
peg->dx=(float)(lpPoints[i].x-lpPoints[j].x)/(lpPoints[i].y-lpPoints[j].y);// 该边斜率的倒数
peg->pNext=NULL;
// 插入边
ppeg=pET[lpPoints[k].y-y0];
while(ppeg->pNext)
ppeg=ppeg->pNext;
ppeg->pNext=peg;
}// end if
}// end for i
// 扫描
for(i=y0;i<=y1;i++)
{
LPEdge peg0=pET[i-y0]->pNext;
LPEdge peg1=pET[i-y0];
if(peg0)// 有新边加入
{
while(peg1->pNext)
peg1=peg1->pNext;
peg1->pNext=pAET->pNext;
pAET->pNext=peg0;
}
// 按照x递增排序pAET
peg0=pAET;
while(peg0->pNext)
{
LPEdge pegmax=peg0;
LPEdge peg1=peg0;
LPEdge pegi=NULL;
while(peg1->pNext)
{
if(peg1->pNext->x>pegmax->pNext->x)
pegmax=peg1;
peg1=peg1->pNext;
}
pegi=pegmax->pNext;
pegmax->pNext=pegi->pNext;
pegi->pNext=pAET->pNext;
pAET->pNext=pegi;
if(peg0 == pAET)
peg0=pegi;
}
// 遍历活边表,画线
peg0=pAET;
while(peg0->pNext)
{
if(peg0->pNext->pNext)
{
dda_line((int)peg0->pNext->x,i,(int)peg0->pNext->pNext->x,i,nColor);
peg0=peg0->pNext->pNext;
}
else
break;
}
// 把ymax=i的节点从活边表删除并把每个节点的x值递增dx
peg0=pAET;
while(peg0->pNext)
{
if(peg0->pNext->ymax < i+2)
{
peg1=peg0->pNext;
peg0->pNext=peg0->pNext->pNext; //删除
delete peg1;
continue;
}
peg0->pNext->x+=peg0->pNext->dx; //把每个节点的x值递增dx
peg0=peg0->pNext;
}
}
// 删除边表
for(i=0;i<y1-y0;i++)
if(pET[i])
delete pET[i];
if(pAET)
delete pAET;
if(pET)
delete[] pET;
}
void CXiaoguanView::Onxiaoguanfilled()
{
AfxMessageBox("可以填充你所选择的颜色了");
// TODO: Add your command handler code here
n==9;
FillPolygon(lpPoints,nCount,color);
}
void CXiaoguanView::OnxiaoguanColor()
{
CColorDialog d;
if(d.DoModal()==IDOK)
color=d.GetColor();
// TODO: Add your command handler code here
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -