Files
2024-12-02 21:40:21 +08:00

237 lines
6.0 KiB
C++

// TestView.cpp : implementation of the CTestView class
//
#include "stdafx.h"
#include "Test.h"
#include "math.h" //数学头文件
#define Round(d) int(floor(d + 0.5)) // 四舍五入宏定义
#include "TestDoc.h"
#include "TestView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CTestView
IMPLEMENT_DYNCREATE(CTestView, CView)
BEGIN_MESSAGE_MAP(CTestView, CView)
//{{AFX_MSG_MAP(CTestView)
ON_WM_MOUSEMOVE()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_COMMAND(IDM_DRAWPIC, OnDrawpic)
//}}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()
/////////////////////////////////////////////////////////////////////////////
// CTestView construction/destruction
CTestView::CTestView()
{
// TODO: add construction code here
m_AbleToLeftBtn = FALSE;
m_AbleToMove = FALSE;
m_i = -1;
P[0] = CPoint(900, 150);
P[1] = CPoint(960, 300);
P[2] = CPoint(1050, 450);
P[3] = CPoint(900, 600);
P[4] = CPoint(750, 450);
P[5] = CPoint(840, 300);
P[6] = CPoint(900, 150);
}
CTestView::~CTestView()
{
}
BOOL CTestView::PreCreateWindow(CREATESTRUCT &cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CTestView drawing
void CTestView::OnDraw(CDC *pDC)
{
CTestDoc *pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
CRect rect; // 定义客户区
GetClientRect(&rect); // 获得客户区的大小
CDC MemDC; // 内存DC
CBitmap NewBitmap, *pOldBitmap; // 内存中承载图像的临时位图
MemDC.CreateCompatibleDC(pDC); // 建立与屏幕pDC兼容的MemDC
NewBitmap.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height()); // 创建兼容位图
pOldBitmap = MemDC.SelectObject(&NewBitmap); // 将兼容位图选入MemDC
MemDC.FillSolidRect(rect, pDC->GetBkColor()); // 按原来背景填充客户区,否则是黑色
CPen NewPen, *pOldPen;
NewPen.CreatePen(PS_SOLID, 3, RGB(0, 0, 0));
pOldPen = MemDC.SelectObject(&NewPen);
MemDC.MoveTo(P[0]);
MemDC.Ellipse(P[0].x - 2, P[0].y - 2, P[0].x + 2, P[0].y + 2); // 绘制控制多边形顶点
for (int i = 1; i < 7; i++)
{
MemDC.LineTo(P[i]);
MemDC.Ellipse(P[i].x - 2, P[i].y - 2, P[i].x + 2, P[i].y + 2);
}
if (m_i != -1)
{
CString str;
str.Format("x=%d,y=%d", P[m_i].x, P[m_i].y);
MemDC.TextOut(P[m_i].x + 5, P[m_i].y + 5, str);
}
B3Curves(P, &MemDC);
pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &MemDC, 0, 0, SRCCOPY); // 将内存位图拷贝到屏幕
MemDC.SelectObject(pOldPen);
NewPen.DeleteObject();
MemDC.SelectObject(pOldBitmap); // 恢复位图
NewBitmap.DeleteObject(); // 删除位图
MemDC.DeleteDC(); // 删除MemDC
}
/////////////////////////////////////////////////////////////////////////////
// CTestView printing
BOOL CTestView::OnPreparePrinting(CPrintInfo *pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
void CTestView::OnBeginPrinting(CDC * /*pDC*/, CPrintInfo * /*pInfo*/)
{
// TODO: add extra initialization before printing
}
void CTestView::OnEndPrinting(CDC * /*pDC*/, CPrintInfo * /*pInfo*/)
{
// TODO: add cleanup after printing
}
/////////////////////////////////////////////////////////////////////////////
// CTestView diagnostics
#ifdef _DEBUG
void CTestView::AssertValid() const
{
CView::AssertValid();
}
void CTestView::Dump(CDumpContext &dc) const
{
CView::Dump(dc);
}
CTestDoc *CTestView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CTestDoc)));
return (CTestDoc *)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CTestView message handlers
void CTestView::B3Curves(CPoint q[], CDC *pDC)
{
CPoint p;
double F03, F13, F23, F33;
// 设置起点
p.x = Round((q[0].x + 4.0 * q[1].x + q[2].x) / 6.0);
p.y = Round((q[0].y + 4.0 * q[1].y + q[2].y) / 6.0);
pDC->MoveTo(p);
// 使用红色画笔
CPen NewPen(PS_SOLID, 2, RGB(255, 0, 0));
CPen *pOldPen = pDC->SelectObject(&NewPen);
// 计算B样条曲线点
for (int i = 0; i < 7; i++)
{
for (double t = 0; t <= 1.0; t += 0.05)
{
// B样条基函数
F03 = (-t * t * t + 3 * t * t - 3 * t + 1) / 6.0;
F13 = (3 * t * t * t - 6 * t * t + 4) / 6.0;
F23 = (-3 * t * t * t + 3 * t * t + 3 * t + 1) / 6.0;
F33 = t * t * t / 6.0;
// 计算曲线上的点
int j = i % 7; // 循环索引确保首尾相连
int j1 = (i + 1) % 7;
int j2 = (i + 2) % 7;
int j3 = (i + 3) % 7;
p.x = Round(q[j].x * F03 + q[j1].x * F13 + q[j2].x * F23 + q[j3].x * F33);
p.y = Round(q[j].y * F03 + q[j1].y * F13 + q[j2].y * F23 + q[j3].y * F33);
pDC->LineTo(p);
}
}
pDC->SelectObject(pOldPen);
NewPen.DeleteObject();
}
void CTestView::OnMouseMove(UINT nFlags, CPoint point) // 鼠标移动函数
{
// TODO: Add your message handler code here and/or call default
if (TRUE == m_AbleToMove)
P[m_i] = point;
m_i = -1;
int i;
for (i = 0; i < 7; i++)
{
if ((point.x - P[i].x) * (point.x - P[i].x) + (point.y - P[i].y) * (point.y - P[i].y) < 50)
{
m_i = i;
m_AbleToLeftBtn = TRUE;
SetCursor(LoadCursor(NULL, IDC_SIZEALL)); // 改变为十字箭头光标
break;
}
}
if (10 == i)
{
m_i = -1;
}
Invalidate(FALSE);
CView::OnMouseMove(nFlags, point);
}
void CTestView::OnLButtonDown(UINT nFlags, CPoint point) // 鼠标左键按下函数
{
// TODO: Add your message handler code here and/or call default
if (m_AbleToLeftBtn == TRUE)
m_AbleToMove = TRUE;
CView::OnLButtonDown(nFlags, point);
}
void CTestView::OnLButtonUp(UINT nFlags, CPoint point) // 鼠标左键弹起函数
{
// TODO: Add your message handler code here and/or call default
m_AbleToLeftBtn = FALSE;
m_AbleToMove = FALSE;
m_i = 0;
CView::OnLButtonUp(nFlags, point);
}
void CTestView::OnDrawpic()
{
// TODO: Add your command handler code here
MessageBox("请直接拖动控制多边形顶点观察效果!", "信息", MB_ICONINFORMATION | MB_OK);
}