LOGFONT成员含义

 

LOGFONT成员含义

LONG  lfHeight;                // 指定逻辑单位的字符或者字符元高度,0默认值。
LONG  lfWidth;                 // 指定逻辑单位的字体字符的平均宽度。
LONG  lfEscapement;            // 指定每行文本输出时相对于设备x轴的角度,其单位为1/10度(整行字符)。
LONG  lfOrientation;           // 指定字符基线相对于设备x轴的角度,其单位为1/10度(单个字符)。
LONG  lfWeight;                // 指定字体的重量(粗细),范围0~1000,0默认, 400正常,700粗体(常用FW_xxxx定义的枚举)。
BYTE  lfItalic;                // 此值为TRUE时,字体为斜体。
BYTE  lfUnderline;             // 此值为TRUE时,字体带下划线。
BYTE  lfStrikeOut;             // 此值为TRUE时,字体带删除线。
BYTE  lfCharSet;               // 指定所使用的字符集,如GB2312_CHARSET,CHINESEBIG5_CHARSET等。
BYTE  lfOutPrecision;          // 指定输出精度(枚举OUT_xxxx),它定义了输出与所要求的字体相接近的程度。
BYTE  lfClipPrecision;         // 指定剪辑精度(枚举CLIP_xxxx),它定义了当字符的一部分超过剪辑区域时对字符的剪辑方式。
BYTE  lfQuality;               // 指定输出质量,它定义了GDI在匹配逻辑字体属性到实际的物理字体时所使用的方式。
BYTE  lfPitchAndFamily;        // 指定字体的字符间距(xxxx_PITCH)和族(FF_xxxx)。
TCHAR lfFaceName[LF_FACESIZE]; // 字体名称(以'\0'结尾的字符串,NULL默认字体)

注释:
(1)逻辑单位
   设备逻辑单位的具体含义由设备的环境映射方式确定(参见SetMapMode/GetMapMode).
   特别的,MM_TEXT表示逻辑单位是像素.
   根据GetDeviceCaps(hDC, LOGPIXELSY)获取像素和物理尺寸的换算关系,可以计算物理尺寸对应的逻辑尺寸.
   lfHeight = -MulDiv(PointSize, GetDeviceCaps(hDC, LOGPIXELSY), 72); // 1(磅)=1/72(英寸)

(2)字体名
   系统文件夹Fonts下列出了系统已经安装的所有字体.
   也可用函数载入其他的字体文件,比如
   AddFontResource / RemoveFontResource
   AddFontResourceEx / RemoveFontResourceEx
   AddFontMemResourceEx / RemoveFontMemResourceEx

(2)字符集
   显示Unicode字符串时,应使用 DEFAULT_CHARSET
   可以使用GetFontUnicodeRanges确定当前字体支持的UNICODE字符范围.
   当显示多种语言的字符的时候,需要"Big Font"支持.
   参见
   http://msdn.microsoft.com/en-us/library/cc194830.aspx
   http://msdn.microsoft.com/zh-cn/goglobal/bb688134

(3)输出质量
   由于TrueType可以任意缩放,所以不用这个字段.

 

// 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 请在这个代码的基础上修改,使最终呈现的效果和我给你的图片上一样
最新发布
12-27
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值