MFC/图形综合/交互式

  1. 添加变量以及函数

1.1变量

private:

CPoint m_ptStart, m_ptEnd;

UINT m_mode;//模态

COLORREF m_color;//声明

CArray<CPoint, CPoint>m_ptArray;

int m_width;

double r;

CPoint m_ptLT, m_ptRB;//拉框的左上和右下

int m_ist;//记录鼠标左键按下的状态

1.2函数

public:

void DDALine(CDC* pDC, int x0, int y0, int x1, int y1, COLORREF color,int width);

void DDADashLine(CDC* pDC, int x0, int y0, int x1, int y1, COLORREF color,int width);

void MidLine(CDC* pDC, int x0, int y0, int x1, int y1, COLORREF color,int width);

void BHLine(CDC* pDC, int x1, int y1, int x2, int y2, COLORREF color,int width);

void DDAWidthLine(CDC* pDC, int x1, int y1, int x2, int y2, COLORREF color, int width);

void BHCircle(CDC* pDC, int x0, int y0, int R, COLORREF color,int width);

void SeadFill(CDC* pDC, int x, int y, COLORREF boundarycolor, COLORREF newcolor);

void Pentagon(CDC* pDC, double r,int width);//空心五角星

void CorrectRect();

BOOL Intersection(double p, double q, double& t0, double &t1);

void Liang_Barsky(CPoint& BPoint, CPoint& EPoint);

void ClearScreen();

  1. 变量的初始化

m_ptStart = m_ptEnd = CPoint(0, 0);

m_mode = 0;//默认为0

m_color = RGB(0, 0, 0);

m_width = 1;

m_ist = 0;

m_ptLT = m_ptRB = CPoint(0,0);

  1. 编写函数

3.1 DDALine

void CFinalExamView::DDALine(CDC* pDC, int x0, int y0, int x1, int y1, COLORREF color, int width)

{

double dx, dy, e, x, y;

dx = x1 - x0;

dy = y1 - y0;

e = (fabs(dx) > fabs(dy)) ? fabs(dx) : fabs(dy);//#include<math.h>

x = x0;

y = y0;

dx /= e;

dy /= e;

for (int i = 1;i <= e;i++)

{

pDC->SetPixel((int)(x + 0.5), (int)(y + 0.5), color);

x += dx;

y += dy;

}

}

3.2 DDADashLine

void CFinalExamView::DDADashLine(CDC* pDC, int x0, int y0, int x1, int y1, COLORREF color, int width)

{

{

double dx, dy, e, x, y;

dx = x1 - x0;

dy = y1 - y0;

e = fabs(dx) > fabs(dy) ? fabs(dx) : fabs(dy);

x = x1; y = y1;

dx /= e;

dy /= e;

for (int i = 1; i <= e; i++)

{

/*pDC->SetPixel(int(x + 0.5), int(y + 0.5), color);

x += dx;

y += dy;*/

if ((i % 40) < 15)

{

pDC->SetPixel(int(x + 0.5), int(y + 0.5), color);

}

else if ((i % 40) < 20)

{

pDC->SetPixel(int(x + 0.5), int(y + 0.5), pDC->GetBkColor());

}

else if (i == 20)

{

pDC->SetPixel(int(x + 0.5), int(y + 0.5), color);

}

else if ((i % 40) < 30)

{

pDC->SetPixel(int(x + 0.5), int(y + 0.5), pDC->GetBkColor());

}

else

{

pDC->SetPixel(int(x + 0.5), int(y + 0.5), color);

}

x += dx;

y += dy;

}

}

}

3.3 MIdLine

void CFinalExamView::MidLine(CDC* pDC, int x0, int y0, int x1, int y1, COLORREF color, int width)

{

int a, b, d, delta1, delta2, x, y;

//两个端点x值相等

if (x0 == x1)

{

if (y0 < y1)

{

for (int i = y0; i < y1; i++)

pDC->SetPixel(x0, i, color);

}

else

{

for (int i = y1; i <= y0; i++)

pDC->SetPixel(x0, i, color);

}

}

//判定斜率,如绝对值大于1,则m为false,否则为true

BOOL m = (fabs(y1 - y0) <= fabs(x1 - x0));

if (x0 > x1)

{

d = x0; y0 = x1; x1 = d;

d = y0; y0 = y1; y1 = d;

}

a = y0 - y1;

b = x1 - x0;

x = x0;

y = y0;

pDC->SetPixel(x, y, color);

//斜率绝对值小于等于1

if (m)

{

//推导的第一种情况(y值递增)

if (y0 <= y1)

{

d = 2 * a + b;

delta1 = 2 * a;

delta2 = 2 * (a + b);

while (x < x1)

{

//如果d<0,取p2(xp+1,yp+1)右上,否则取p1(xp+1,yp)右边

if (d < 0)

{

x++; y++;

d += delta2;

}

else

{

x++;

d += delta1;

}

pDC->SetPixel(x, y, color);

}

}

//推导的第三种情况(y值递减)

else

{

d = 2 * a - b;

delta1 = 2 * a;

delta2 = 2 * (a - b);

while (x < x1)

{

//推导的第二种情况

//若d<0,取p1(xp+1,yp),否则取p2(xp+1,yp-1)

if (d < 0)

{

x++;

d += delta1;

}

else

{

x++; y--;

d += delta2;

}

pDC->SetPixel(x, y, color);

}

}

}

//斜率绝对值大于1

else

{

if (y0 < y1)

{

d = a + 2 * b;

delta1 = 2 * b;

delta2 = 2 * (a + b);

while (y < y1)

{

//若d<0,取p1(xp,yp+1),否则取p1(xp+1,yp+1)

if (d < 0)

{

y++;

d += delta1;

}

else

{

y++; x++;

d += delta2;

}

pDC->SetPixel(x, y, color);

}

}

//课堂推导的第四种情况

else

{

d = a - 2 * b;

delta1 = -2 * b;

delta2 = 2 * (a + -b);

while (y > y1)

{

//若d<0,取p2(xp+1,yp-1),否则取p2(xp,yp-1)

if (d < 0)

{

y--; x++;

d += delta2;

}

else

{

y--;

d += delta1;

}

pDC->SetPixel(x, y, color);

}

}

}

}

3.4 BHLine

void CFinalExamView::BHLine(CDC* pDC, int x1, int y1, int x2, int y2, COLORREF color, int width)

{

int x, y, dx, dy, p;

if (x1 == x2)

{

if (y1 < y2)

{

for (int i = y1; i <= y2; i++)

{

pDC->SetPixel(x1, i, color);

}

}

else

{

for (int i = y2; i <= y1; i++)

{

pDC->SetPixel(x1, i, color);

}

}

return;

}

//斜率>1为FALSE,否则为true

BOOL m = (fabs(y2 - y1) <= fabs(x2 - x1));

//如果x2>x1,交换坐标

if (x1 > x2)

{

p = x1; x1 = x2; x2 = p;

p = y1; y1 = y2; y2 = p;

}

//变量赋初值

x = x1;

y = y1;

dx = x2 - x1;

dy = y2 - y1;

//斜率绝对值<=1

if (m)

{

//第一种情况,Y递增

if (y1 <= y2)

{

p = (dy << 1) - dx;

while (x <= x2)

{

pDC->SetPixel(x, y, color);

if (p < 0) {

x++;

p = p + (dy << 1);

}

else

{

x++; y++;

p = p + ((dy - dx) << 1);

}

}

}

//第三种情况,y递减

else

{

p = dx - (dy << 1);

while (x <= x2)

{

pDC->SetPixel(x, y, color);

if (p < 0)

{

x++;

p = p - (dy << 1);

}

else

{

x++; y--;

p = p - ((dy + dx) << 1);

}

}

}

}

//斜率绝对值大于1

else {

//理论课讨论的第二种情况

if (y1 <= y2)

{

p = (dx << 1) - dy;

while (y <= y2)

{

pDC->SetPixel(x, y, color);

if (p < 0)

{

y++;

p = p + (dx << 1);

}

else

{

y++; x++;

p = p + ((dx - dy) << 1);

}

}

}

//第四种情况,y递减

else

{

p = (dx << 1) + dy;

while (y >= y2)

{

pDC->SetPixel(x, y, color);

if (p < 0)

{

y--;

p = p + (dx << 1);

}

else

{

y--; x++;

p = p + ((dx + dy) << 1);

}

}

}

}

}

3.5  DDAWidthLine

void CFinalExamView::DDAWidthLine(CDC* pDC, int x1, int y1, int x2, int y2, COLORREF color, int width)

{

double dx, dy, e, x, y;

dx = x2 - x1;

dy = y2 - y1;

e = (fabs(dx) > fabs(dy)) ? fabs(dx) : fabs(dy);

x = x1;

y = y1;

dx /= e;

dy /= e;

for (int i = 1;i <= e;i++)

{

//pDC->SetPixel(int(x + 0.5), int(y + 0.5), color);

for (int j = (1 - width) / 2;j <= width / 2;j++)

{

for (int k = (1 - width) / 2;k <= width / 2;k++)

{

pDC->SetPixel(int(x + 0.5) + j, int(y + 0.5) + k, color);

}

x += dx;

y += dy;

}

}

}

3.6  BHCircle

void CFinalExamView::BHCircle(CDC* pDC, int x0, int y0, int R, COLORREF color, int width)

{

int x, y, p;

x = 0;

y = R;

p = 3 - (R << 1);

for (;x <= y;x++)

{

pDC->SetPixel(x + x0, y + y0, color);

pDC->SetPixel(-x + x0, y + y0, color);

pDC->SetPixel(x + x0, -y + y0, color);

pDC->SetPixel(-x + x0, -y + y0, color);

pDC->SetPixel(y + x0, x + y0, color);

pDC->SetPixel(-y + x0, x + y0, color);

pDC->SetPixel(y + x0, -x + y0, color);

pDC->SetPixel(-y + x0, -x + y0, color);

if (p < 0)

{

p += ((x << 2) + 6);

}

else

{

p = (((x - y) << 2) + 10);

y--;

}

}

}

3.7  SeedFill

void CFinalExamView::SeedFill(CDC* pDC, int x, int y, COLORREF boundarycolor, COLORREF newcolor)

{

//首先定义一些变量

//然后是栈,压栈弹栈

//从栈里面取出一个点,判定是否填充,一直填充到边界(一行一行)

//检查上下两行,如果不是新颜色,就把种子填充进去

//第一行是最特殊的行,上下两行搜索的方式都是从右边向左边填充(用while循环做)

int x0, y0, xr, xl, xid;

int flag, xnextspan;//span像素段,flag一般用1或者0两种状态(逻辑变量:true or false)

stack<CPoint> s;//栈对象

CPoint p;

s.push(CPoint(x, y));//第一颗种子

while (!s.empty())

{//如果不是空的就开始绘制

p = s.top(); s.pop();//首先得到的要素,取出来之后就不需要了

pDC->SetPixel(p.x, p.y, newcolor);//给种子填充新的颜色

x = p.x;y = p.y;//把xy初始化,后面使用就偏离

x0 = x + 1;//开始向右边填充

while (pDC->GetPixel(x0, y) != boundarycolor)//不是边界色就填充

{

pDC->SetPixel(x0, y, newcolor);

x0++;//开始循环,到边界时候跳出循环

}

xr = x0 - 1;//最右边的点,如果上一行也是xr就压栈

x0 = x - 1;//开始向左边

while (pDC->GetPixel(x0, y) != boundarycolor)

{

pDC->SetPixel(x0, y, newcolor);

x0--;//左边循环

}

xl = x0 + 1;//一行搞定后,就开始上下两行

//-----------以下只是判定种子要不要入栈-------------

y0 = y;//种子所在的行

for (int i = 1;i >= -1;i -= 2)

{

//当前的线为1,减二开始循环,大于-1就退出循环

//先检查的是上面的一行,然后-2是下面的一行

x0 = xr;//从右边开始上下两行

y = y0 + i;//得到点后根据四连通性进行判定

while (x0 >= xl)

{

flag = 0;

while ((pDC->GetPixel(x0, y) != boundarycolor)

&& (pDC->GetPixel(x0, y) != newcolor)

&& (x0 > xl))

{

if (0 == flag)

{

flag = 1;

xid = x0;//记录

}

x0--;//跳出循环

}//判定一下,要不要入栈

if (1 == flag)

{

s.push(CPoint(xid, y));

flag = 0;//压进去后,还需要进行清理

}

//记录最左侧的点

xnextspan = x0;//相等就偏移,然后退出循环

while ((pDC->GetPixel(x0, y) == boundarycolor) ||

(pDC->GetPixel(x0, y) == newcolor) && (x0 > xl))

x0--;

if (xnextspan == x0) x0--;

}

}

}

}

3.8 Pentagon

void CFinalExamView::Pentagon(CDC* pDC, double r, int width)

{

//颜色填充可以使用seedfill

CPoint pts[5];//五个顶点

r = 55;

for (int i = 0;i < 5;i++)

{

pts[i].x = (long)(150 - r * sin((i * 72 + 36) * 2 * 3 * 3.14 / 360));

pts[i].y = (long)(150 + r * cos((i * 72 + 36) * 2 * 3 * 3.14 / 360));

}//先将笔移动到第一个点,将其与第二个点连接

for (int i = 0;i < 5;i++)

{

pDC->MoveTo(pts[i]);//线段起点

pDC->LineTo(pts[(i + 2) % 5]);//线段终点

}

}

3.9  CorrectRect

void CFinalExamView::CorrectRect()

{

int x, y;

if (m_ptLT.x > m_ptRB.x)

{

x = m_ptLT.x;

m_ptLT.x = m_ptRB.x;

m_ptRB.x = x;

}

if (m_ptLT.y < m_ptRB.y)

{

y = m_ptLT.y;

m_ptLT.y = m_ptRB.y;

m_ptRB.y = y;

}

}

3.10  Intersection

BOOL CFinalExamView::Intersection(double p, double q, double& t0, double& t1)

{

double u;

if (p < 0)

{

u = q / p;

if (u > t1)//线段不在裁剪框内

return FALSE;

else if (u > t0)

t0 = u; //入边取大

}

else if (p > 0)

{

u = q / p;

if (u < t0)//线段不在裁剪框内

return FALSE;

else if (u < t1)

t1 = u;//出边取小

}

else if (q < 0)

return FALSE;

return TRUE;

}

3.11  Liang_Barsky

void CFinalExamView::Liang_Barsky(CPoint& BPoint, CPoint& EPoint)

{

double t0, t1, dx, dy;

t0 = 0.0;

t1 = 1.0;

dx = EPoint.x - BPoint.x;

if (!Intersection(-dx, BPoint.x - m_ptLT.x, t0, t1))

return;

if (!Intersection(dx, m_ptRB.x - BPoint.x, t0, t1))

return;

dy = EPoint.y - BPoint.y;

if (!Intersection(-dy,BPoint.y - m_ptRB.y,t0,t1))

return;

if (!Intersection(dy, m_ptLT.y - BPoint.y, t0, t1))

return;

EPoint.x = (int)(BPoint.x + t1 * dx);

EPoint.y = (int)(BPoint.y + t1 * dy);

BPoint.x = (int)(BPoint.x + t0 * dx);

BPoint.y = (int)(BPoint.y + t0 * dy);

}

3.12  ClearScrean

void CFinalExamView::ClearScreen()

{

CClientDC dc(this);

CRect window;

GetClientRect(window);//讲绘制区域设置城客户区

dc.SelectStockObject(WHITE_PEN);

dc.SelectStockObject(WHITE_BRUSH);

dc.Rectangle(window);

}

  1. 消息处理函数

4.1线宽

void CFinalExamView::OnWidth()

{

CWidthDialog dlg;

if (IDOK == dlg.DoModal())

{

m_width = dlg.m_widthDlg;

}

}

4.2颜色

void CFinalExamView::OnColor()

{

CColorDialog dlg;

if (IDOK == dlg.DoModal())

{

m_color = dlg.GetColor();

}

}

4.3鼠标左键摁下

void CFinalExamView::OnLButtonDown(UINT nFlags, CPoint point)

{

m_ptStart = point;

m_ptArray.Add(point);

}

4.4鼠标左键抬起

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

{

m_ptEnd = point;

CDC* pDC = GetDC();

switch (m_mode)

{

case 1://DDALine

DDALine(pDC, m_ptStart.x, m_ptStart.y,

m_ptEnd.x, m_ptEnd.y, m_color,m_width);

break;

case 2://MidLine

MidLine(pDC, m_ptStart.x, m_ptStart.y,

m_ptEnd.x, m_ptEnd.y, m_color, m_width);

break;

case 3://BHLine

BHLine(pDC, m_ptStart.x, m_ptStart.y,

m_ptEnd.x, m_ptEnd.y, m_color, m_width);

break;

case 4://DDADashLine

DDADashLine(pDC, m_ptStart.x, m_ptStart.y,

m_ptEnd.x, m_ptEnd.y, m_color, m_width);

break;

case 5://BHCircle

{int R = int(sqrt((m_ptEnd.x - m_ptStart.x) * (m_ptEnd.x - m_ptStart.x) +

(m_ptEnd.y - m_ptStart.y) * (m_ptEnd.y - m_ptStart.y)));

BHCircle(pDC, m_ptStart.x, m_ptStart.y,

R, m_color, m_width);

}

break;

case 6://Rectangle

pDC->Rectangle(m_ptStart.x, m_ptStart.y, m_ptEnd.x, m_ptEnd.y);

break;

case 7://Polygon

for (int i = 0;i <= m_ptArray.GetSize() - 2;i++)

{

CPoint p1, p2;

p1 = m_ptArray.GetAt(i);

p2 = m_ptArray.GetAt(i + 1);

pDC->MoveTo(p1);

pDC->LineTo(p2);

}

break;

case 8://Polyline

{

for (int i = 0;i <= m_ptArray.GetSize() - 2;i++)

{

CPoint p1, p2;

p1 = m_ptArray.GetAt(i);

p2 = m_ptArray.GetAt(i + 1);

pDC->LineTo(p2);

}

}

break;

case 9://SeedFill

SeadFill(pDC, point.x, point.y, RGB(0, 0, 0), RGB(0, 255, 255));

break;

case 10: // DDAWidthLine

DDAWidthLine(pDC, m_ptStart.x, m_ptStart.y,

m_ptEnd.x, m_ptEnd.y, m_color, m_width);

break;

case 11://pentagon

Pentagon(pDC, r, m_width);

break;

case 12:

m_ptLT = m_ptStart;

m_ptRB = m_ptEnd;

CorrectRect();

pDC->Rectangle(m_ptLT.x,m_ptLT.y,

m_ptRB.x,m_ptRB.y);

break;

case 13:

pDC->MoveTo(m_ptStart);

pDC->LineTo(m_ptEnd);

int nDrawmode = pDC->SetROP2(R2_NOT);

pDC->MoveTo(m_ptStart);

pDC->LineTo(m_ptEnd);

Liang_Barsky(m_ptStart, m_ptEnd);

pDC->SetROP2(nDrawmode);

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

CPen* oldPen = pDC->SelectObject(&penRed);

pDC->MoveTo(m_ptStart);

pDC->LineTo(m_ptEnd);

pDC->SelectObject(oldPen);

break;

}

ReleaseDC(pDC);

CView::OnLButtonUp(nFlags, point);

}

4.4鼠标双击

void CFinalExamView::OnLButtonDblClk(UINT nFlags, CPoint point)

{

CView::OnLButtonDblClk(nFlags, point);

m_ptArray.Add(point);

m_ptArray.Add(m_ptEnd);

CDC* pDC = GetDC();

for (int i = 0;i <= m_ptArray.GetSize() - 2;i++)

{

CPoint p1, p2;

p1 = m_ptArray.GetAt(i);

p2 = m_ptArray.GetAt(i + 2);

DDALine(pDC, p1.x, p1.y, p2.x, p2.y, m_color, m_width);

}

if (7 == m_mode)

Invalidate();

m_ptArray.RemoveAll();

}

4.5鼠标移动

void CFinalExamView::OnMouseMove(UINT nFlags, CPoint point)

{

//橡皮筋技术

CDC* pDC = GetDC();

int nDrawmode = pDC->SetROP2(R2_NOT);

pDC->SelectStockObject(NULL_BRUSH);

if (1 == m_ist)

{

pDC->MoveTo(m_ptStart);

pDC->LineTo(m_ptEnd);

m_ptEnd = point;

pDC->MoveTo(m_ptStart);

pDC->LineTo(m_ptEnd);

}

pDC->SetROP2(nDrawmode);

ReleaseDC(pDC);

}

结果展示

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值