// WaterLevelCurveSystemView.cpp: CWaterLevelCurveSystemView 类的实现
#include "pch.h"
#include "WaterLevelCurveSystem.h"
#include "WaterLevelCurveSystemDoc.h"
#include "WaterLevelCurveSystemView.h"
#include "CInputDialog.h"
#include <vector>
#include <algorithm>
using namespace std;
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
IMPLEMENT_DYNCREATE(CWaterLevelCurveSystemView, CView)
BEGIN_MESSAGE_MAP(CWaterLevelCurveSystemView, CView)
ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CWaterLevelCurveSystemView::OnFilePrintPreview)
ON_WM_CONTEXTMENU()
ON_WM_RBUTTONUP()
ON_COMMAND(ID_EXTEND_CURVE, &CWaterLevelCurveSystemView::OnExtendCurve)
END_MESSAGE_MAP()
// 构造函数:初始化成员变量
CWaterLevelCurveSystemView::CWaterLevelCurveSystemView() noexcept
: m_extendAtZ(-1.0)
, m_bDrawExtend(false)
{
}
// 析构函数
CWaterLevelCurveSystemView::~CWaterLevelCurveSystemView()
{
}
// 预创建窗口
BOOL CWaterLevelCurveSystemView::PreCreateWindow(CREATESTRUCT& cs)
{
return CView::PreCreateWindow(cs);
}
// 主绘图函数
void CWaterLevelCurveSystemView::OnDraw(CDC* pDC)
{
ASSERT_VALID(pDC);
CWaterLevelCurveSystemDoc* pDoc = GetDocument();
if (!pDoc) return;
CRect rect;
GetClientRect(&rect);
const int margin = 100;
const int width = rect.Width() - 2 * margin;
const int height = rect.Height() - 2 * margin;
// ====== 1. 数据定义 ======
vector<double> z_q_z = { 60.5, 61.0, 61.5, 62.0, 62.5 }; // Z-Q 水位
vector<double> z_q_q = { 100, 200, 600, 1500, 2600 }; // Z-Q 流量
vector<double> z_ar_z = { 60.5, 61.0, 61.5, 62.0, 62.5 }; // Z-A√R 水位
vector<double> z_ar_ar = { 0, 400, 600, 1200, 1700 }; // Z-A√R 值
vector<double> q_ar_q = { 500, 1000, 1500, 2000, 2500, 3000 }; // Q-A√R 流量
vector<double> q_ar_ar = { 700, 1200, 1800, 2400, 2800, 3400 }; // Q-A√R 值
// ====== 2. 坐标映射 Lambda(全部在 OnDraw 内部定义)======
auto X_Q = [&](double q) -> int {
if (q < 0 || q > 7000) return -1;
return margin + static_cast<int>((q / 7000.0) * width);
};
auto X_AR = [&](double ar) -> int {
if (ar < 0 || ar > 7200) return -1;
return margin + static_cast<int>((ar / 7200.0) * width);
};
auto Y_Z = [&](double z) -> int {
if (z < 60.0 || z > 64.0) return -1;
return (rect.bottom - margin) - static_cast<int>(((z - 60.0) / 4.0) * height);
};
// ====== 3. 绘制标题 ======
LOGFONT lf = {};
wcscpy_s(lf.lfFaceName, L"楷体");
lf.lfHeight = -35;
lf.lfWeight = FW_BOLD;
lf.lfQuality = CLEARTYPE_QUALITY;
CFont titleFont;
titleFont.CreateFontIndirect(&lf);
CFont* pOldFont = pDC->SelectObject(&titleFont);
pDC->SetTextColor(RGB(173, 216, 230)); // 浅蓝色
pDC->SetTextAlign(TA_CENTER | TA_TOP);
pDC->TextOut(rect.Width() / 2, 50, L"水位流量关系图");
pDC->SelectObject(pOldFont);
titleFont.DeleteObject();
// ====== 4. 绘制三条曲线 ======
// --- 4.1 Z-Q 曲线(蓝色实线)---
CPen penZQ(PS_SOLID, 2, RGB(0, 0, 255));
CPen* pOldPen = pDC->SelectObject(&penZQ);
for (size_t i = 1; i < z_q_z.size(); ++i) {
int x1 = X_Q(z_q_q[i - 1]);
int y1 = Y_Z(z_q_z[i - 1]);
int x2 = X_Q(z_q_q[i]);
int y2 = Y_Z(z_q_z[i]);
if (x1 >= 0 && x2 >= 0 && y1 >= 0 && y2 >= 0) {
pDC->MoveTo(x1, y1);
pDC->LineTo(x2, y2);
}
}
// --- 4.2 Z-A√R 曲线(绿色实线)---
CPen penZAR(PS_SOLID, 2, RGB(0, 128, 0));
pDC->SelectObject(&penZAR);
for (size_t i = 1; i < z_ar_z.size(); ++i) {
int x1 = X_AR(z_ar_ar[i - 1]);
int y1 = Y_Z(z_ar_z[i - 1]);
int x2 = X_AR(z_ar_ar[i]);
int y2 = Y_Z(z_ar_z[i]);
if (x1 >= 0 && x2 >= 0 && y1 >= 0 && y2 >= 0) {
pDC->MoveTo(x1, y1);
pDC->LineTo(x2, y2);
}
}
// --- 4.3 Q-A√R 曲线(紫色实线)---
// 将 A√R 映射为虚拟水位 Z(60~64),以便共用 Y 轴
CPen penQAR(PS_SOLID, 2, RGB(128, 0, 128));
pDC->SelectObject(&penQAR);
for (size_t i = 1; i < q_ar_q.size(); ++i) {
double z1 = 60.0 + (q_ar_ar[i - 1] / 7200.0) * 4.0; // 虚拟 Z
double z2 = 60.0 + (q_ar_ar[i] / 7200.0) * 4.0;
int x1 = X_Q(q_ar_q[i - 1]);
int y1 = Y_Z(z1);
int x2 = X_Q(q_ar_q[i]);
int y2 = Y_Z(z2);
if (x1 >= 0 && x2 >= 0 && y1 >= 0 && y2 >= 0) {
pDC->MoveTo(x1, y1);
pDC->LineTo(x2, y2);
}
}
pDC->SelectObject(pOldPen); // 恢复画笔
// ====== 5. 延长线绘制(仅当启用)======
if (m_bDrawExtend && m_extendAtZ > 60.0 && m_extendAtZ <= 64.0)
{
CPen dashPen(PS_DOT, 1, RGB(255, 0, 0)); // 红色虚线
pDC->SelectObject(&dashPen);
size_t n = z_q_z.size();
double dq_dz = (z_q_q[n - 1] - z_q_q[n - 2]) / (z_q_z[n - 1] - z_q_z[n - 2]);
double q_ext = z_q_q[n - 1] + dq_dz * (m_extendAtZ - z_q_z[n - 1]);
pDC->MoveTo(X_Q(z_q_q[n - 1]), Y_Z(z_q_z[n - 1]));
pDC->LineTo(X_Q(q_ext), Y_Z(m_extendAtZ));
// 标记延长点
CRect markRect(X_Q(q_ext) - 5, Y_Z(m_extendAtZ) - 5, X_Q(q_ext) + 5, Y_Z(m_extendAtZ) + 5);
pDC->Ellipse(markRect);
pDC->SelectObject(pOldPen);
}
// ====== 6. 右下角个人信息 ======
pDC->SetTextColor(RGB(173, 216, 230));
pDC->SetTextAlign(TA_RIGHT | TA_BOTTOM);
CString info;
info.Format(L"学号: %s, 姓名: %s, 日期: %s", L"20241010347", L"张诗琦", L"2025-12-25");
pDC->TextOut(rect.Width() - 20, rect.Height() - 20, info);
}
// 打印预览
void CWaterLevelCurveSystemView::OnFilePrintPreview()
{
#ifndef SHARED_HANDLERS
AFXPrintPreview(this);
#endif
}
// 打印准备
BOOL CWaterLevelCurveSystemView::OnPreparePrinting(CPrintInfo* pInfo)
{
return DoPreparePrinting(pInfo);
}
void CWaterLevelCurveSystemView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) {}
void CWaterLevelCurveSystemView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) {}
// 右键菜单
void CWaterLevelCurveSystemView::OnRButtonUp(UINT /*nFlags*/, CPoint point)
{
ClientToScreen(&point);
OnContextMenu(this, point);
}
void CWaterLevelCurveSystemView::OnContextMenu(CWnd* /*pWnd*/, CPoint point)
{
#ifndef SHARED_HANDLERS
theApp.GetContextMenuManager()->ShowPopupMenu(IDR_POPUP_EDIT, point.x, point.y, this, TRUE);
#endif
}
// 菜单命令:延长曲线
void CWaterLevelCurveSystemView::OnExtendCurve()
{
CInputDialog dlg;
if (dlg.DoModal() == IDOK) {
if (abs(dlg.m_dWaterLevel - 63.3) < 0.1) {
m_extendAtZ = dlg.m_dWaterLevel;
m_bDrawExtend = true;
Invalidate();
}
else {
AfxMessageBox(L"仅支持水位 63.3m 附近的延长!");
}
}
}
#ifdef _DEBUG
void CWaterLevelCurveSystemView::AssertValid() const
{
CView::AssertValid();
}
void CWaterLevelCurveSystemView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CWaterLevelCurveSystemDoc* CWaterLevelCurveSystemView::GetDocument() const
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CWaterLevelCurveSystemDoc)));
return reinterpret_cast<CWaterLevelCurveSystemDoc*>(m_pDocument);
}
#endif
请在这个代码的基础上修改,使最终呈现的效果和我给你的图片上一样
最新发布