简介本资源是一份面向C#与Halcon联合开发者的实战示例工程聚焦于在Halcon图形窗口中动态渲染自定义文本这一典型交互需求解决工业视觉应用中状态提示、调试信息叠加、结果标注等实际问题。压缩包共37个文件包含11个核心C#源码如Form1.cs、HalconView.cs、3个可执行程序exe、2个Halcon相关动态库dll及配套配置文件config、resx、csproj等完整呈现了从窗体集成、字体设置set_display_font到消息显示disp_message的全流程实现逻辑。资源大小为10.8MB结构清晰支持直接编译运行与二次扩展。已有1352人学习下载读者可直接获取可运行的VS解决方案含sln/suo项目文件、带注释的源码、预编译可执行文件及调试所需的pdb符号文件快速掌握C#调用Halcon外部函数实现文本渲染的关键接口与工程组织方式。1. 在 Halcon 窗体上“写字”不是调用disp_message这是在 UI 层做原生渲染绕过 Halcon 内置显示管线实现透明、抗锯齿、动态坐标系文字叠加你有没有试过disp_message发现文字总被图像裁剪、无法旋转对齐 ROI 边缘、换行错位、中文模糊发虚甚至想把检测结果里的毫米值贴在工件轮廓正上方却卡在“文字位置随缩放跳变”上这不是你代码写错了——是disp_message本质属于 Halcon 的绘图层drawing layer它和图像像素绑定、不参与窗体坐标系变换、不响应 DPI 缩放、不支持 alpha 混合。而标题里说的“通过外部函数在 Halcon 窗体上写字”指的是绕过 Halcon 自带的显示逻辑直接操作其底层窗体句柄HWND用 Windows GDI/GDI 或 Qt 原生 API 在窗体客户区绘制文字。这让你能① 文字永远居于图像顶层且不遮挡交互如 ROI 拖拽② 支持任意字体、字号、透明度、旋转角度③ 文字坐标可映射到图像物理坐标比如在 (x120.5, y87.3) 处画“OK”哪怕图像缩放 300% 也精准贴合④ 和 Qt 主界面风格统一如果你用 Qt 封装 Halcon。这不是炫技而是产线视觉系统里做高精度测量标注、多语言 UI 适配、AR 式引导提示的刚需路径。本文只讲 Windows 平台下用 C/Qt 调用 Halcon 的真实落地方案——不依赖hcanvas.dll它已废弃且文档缺失不碰HDevEngine太重就用最稳的HWindowHandleGetDCTextOutW三板斧从零跑通。2. 为什么必须绕开disp_messageHalcon 显示管线的三层隔离与外部渲染的不可替代性2.1 Halcon 窗体的本质一个托管 HWND但不开放 HDC 获取接口Halcon 的HWindow对象如HWindowX或HWindow在 Windows 下底层封装了一个标准HWND可通过HWindow::GetWindowHandle()或HDevWindowStack::GetActiveWindowHandle()提取。但 Halcon刻意屏蔽了 HDC设备上下文的直接暴露——你无法像普通 Win32 窗体那样GetDC(hwnd)后自由绘图。原因很实际Halcon 需要独占图像渲染管线以保证实时性尤其在高速采集时若允许外部随意BitBlt或TextOut极易引发 GDI 资源竞争、画面撕裂或WM_PAINT冲突。所以官方只提供disp_message这种“安全沙盒式”文本输出所有文字都走 Halcon 自己的光栅化引擎与图像帧同步刷新。但代价是它完全脱离 Windows UI 生态——不响应系统 DPI 设置高分屏文字糊成一片、不支持 OpenType 特性连微软雅黑的 ClearType 都关不掉、坐标系固定为窗体像素而非逻辑坐标。提示disp_message的(Row, Column)参数是窗体客户区像素坐标不是图像坐标。当你用set_part缩放图像时Row/Column不会自动缩放导致文字“漂移”。这是产线调试中最常被骂的玄学问题。2.2 外部函数注入的唯一合法入口HWindow::SetPartHWindow::GetWindowHandle()组合Halcon 官方留了一条窄缝HWindow::SetPart()函数用于设置图像显示区域即Row1, Column1, Row2, Column2但它会触发WM_SIZE消息并重绘窗体而HWindow::GetWindowHandle()返回的HWND是真实有效的。这意味着只要你在WM_PAINT消息处理中用GetDC获取 HDC再用SetMapMode切换到MM_ANISOTROPIC模式就能把文字坐标映射到图像物理坐标系。这才是“在 Halcon 窗体上写字”的技术本质——不是往 Halcon 里塞文字而是往 Halcon 占用的 HWND 上叠一层 Windows 原生文字。关键点在于必须在WM_PAINT中绘制否则会被 Halcon 的后续BitBlt覆盖必须用BeginPaint/EndPaint而非GetDC/ReleaseDC否则破坏 Halcon 的 GDI 资源管理。2.3 Qt 场景下的特殊路径QGraphicsViewHWindow嵌套的坐标系对齐陷阱如果你用 Qt 封装 Halcon如QHalconWidget常见错误是直接在QWidget::paintEvent里drawText—— 这会导致文字画在 Qt 窗体层而 Halcon 图像在QGraphicsView的viewport()下两层 Z-order 错乱且缩放时坐标不同步。正确做法是获取HWindow的HWND用QWindow::fromWinId()创建QWindow对象再用QGraphicsProxyWidget将其嵌入QGraphicsScene。这样文字绘制和图像渲染共享同一坐标系。热词里提到的 “panel toplevel 子窗体” 正是此场景——你需要把文字渲染层作为QGraphicsItem添加到同一 scene而非独立 widget。Qt 怎么调用 Halcon的核心难点就在这里不是调用函数而是协调坐标系。3. 用 Windows GDI 在 Halcon 窗体上写第一行字最小可行代码与坐标映射原理3.1 获取 HWND 并监听 WM_PAINT 的完整流程C// 假设你已有 HWindowX hwin; HWND hwnd (HWND)hwin.GetWindowHandle(); // 第一步子类化窗体拦截 WM_PAINT WNDPROC oldWndProc nullptr; LRESULT CALLBACK HookedWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { if (uMsg WM_PAINT) { PAINTSTRUCT ps; HDC hdc BeginPaint(hWnd, ps); // 必须用 BeginPaint // 设置映射模式为 MM_ANISOTROPIC使逻辑坐标与图像坐标对齐 SetMapMode(hdc, MM_ANISOTROPIC); // 获取当前图像显示区域物理坐标 double row1, col1, row2, col2; hwin.GetPart(row1, col1, row2, col2); // 计算缩放比例窗体像素尺寸 / 图像物理尺寸 RECT rc; GetClientRect(hWnd, rc); double scaleX (rc.right - rc.left) / (col2 - col1); double scaleY (rc.bottom - rc.top) / (row2 - row1); // 设置窗口扩展逻辑坐标范围 SetWindowExtEx(hdc, (int)(col2 - col1), (int)(row2 - row1), nullptr); // 设置视口扩展对应窗体像素 SetViewportExtEx(hdc, (int)(rc.right - rc.left), (int)(rc.bottom - rc.top), nullptr); // 现在可以画文字了坐标 (100, 50) 就是图像上的 (100, 50) 像素点 SetTextColor(hdc, RGB(255, 0, 0)); // 红色 SetBkMode(hdc, TRANSPARENT); HFONT hFont CreateFont(-12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, LMicrosoft YaHei); SelectObject(hdc, hFont); WCHAR text[] L检测合格; TextOutW(hdc, 100, 50, text, wcslen(text)); DeleteObject(hFont); EndPaint(hWnd, ps); return 0; // 已处理不再调用原函数 } return CallWindowProc(oldWndProc, hWnd, uMsg, wParam, lParam); } // 在初始化 Halcon 窗体后调用 oldWndProc (WNDPROC)SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)HookedWndProc);这段代码的关键逻辑说明BeginPaint/EndPaint是强制要求否则 Halcon 的WM_PAINT处理器会因 GDI 资源未释放而崩溃SetMapMode(MM_ANISOTROPIC)SetWindowExtEx/SetViewportExtEx是坐标映射的核心——它让(100,50)这个逻辑坐标严格对应图像上第 100 列、第 50 行的像素位置无论窗体是否缩放、是否滚动CreateFont用WCHAR字符串和TextOutW支持中文避免ANSI字体乱码SetBkMode(TRANSPARENT)确保文字背景透明不遮挡图像。3.2 Qt 场景下的等效实现用QPainter替代 GDI但必须绕过QGraphicsView的 viewport// 在你的 QHalconWidget 类中继承自 QWidget void QHalconWidget::paintEvent(QPaintEvent* event) { // 注意这里不能直接 paint因为 Halcon 窗体是独立 HWND // 正确做法获取 Halcon HWND用 QWindow::fromWinId() 创建 proxy HWND hwnd (HWND)m_hwin.GetWindowHandle(); QWindow* win QWindow::fromWinId((WId)hwnd); if (!win || !win-handle()) return; // 获取当前图像显示区域 double row1, col1, row2, col2; m_hwin.GetPart(row1, col1, row2, col2); QRectF imageRect(col1, row1, col2-col1, row2-row1); // 创建 QPainter目标是 Halcon 窗体的 client area QPainter painter(win); painter.setRenderHint(QPainter::Antialiasing); painter.setRenderHint(QPainter::TextAntialiasing); // 设置坐标系映射将图像坐标转为窗体像素坐标 QRect winRect win-geometry(); double scaleX winRect.width() / (col2 - col1); double scaleY winRect.height() / (row2 - row1); QTransform transform; transform.translate(winRect.x(), winRect.y()); transform.scale(scaleX, scaleY); transform.translate(-col1, -row1); painter.setTransform(transform); // 现在 painter 的 (100,50) 就是图像坐标 (100,50) QFont font(Microsoft YaHei, 12, QFont::Normal, true); painter.setFont(font); painter.setPen(QColor(255, 0, 0)); painter.drawText(QPointF(100, 50), OK); }参数说明QTransform构造的四步变换平移→缩放→平移是 Qt 坐标系对齐的黄金公式比手动计算scaleX/scaleY更鲁棒QPainter::Antialiasing开启抗锯齿解决热词里提到的“halcon在图片写入文字”模糊问题QFont构造时第四个参数true表示使用QFont::StyleHint::AnyStyle确保跨平台字体回退。4. 把文字坐标从“窗体像素”升级到“图像物理坐标”支持毫米标注与动态 ROI 跟踪4.1 从像素坐标到世界坐标的三步转换gen_measure_rectangle2→measure_pos→affine_trans_point_2d产线需求从来不是“在 (100,50) 画字”而是“在检测出的螺栓中心右侧 2mm 处画‘扭矩 OK’”。这就需要把 Halcon 的测量结果像素坐标转为物理坐标mm再映射回窗体。典型链路用gen_measure_rectangle2定义测量矩形基于 ROI 或模板匹配结果用measure_pos获取亚像素级边缘点返回Row,Column像素用affine_trans_point_2d将像素点转为世界坐标需提前用calibration_object_model_3d标定相机再用affine_trans_point_2d的逆变换把世界坐标转回窗体像素坐标供TextOutW使用。* Halcon 脚本段获取螺栓中心的世界坐标单位 mm gen_measure_rectangle2 (Row, Column, Phi, Length1, Length2, Width, max, MeasureHandle) measure_pos (ImageReduced, MeasureHandle, 1, 30, all, all, RowEdge, ColumnEdge, Amplitude, Distance) * 假设 RowEdge, ColumnEdge 是边缘点数组取中心 mean (RowEdge, RowCenter) mean (ColumnEdge, ColCenter) * 将像素中心转为世界坐标假设已标定CalibData 包含内参和外参 affine_trans_point_2d (CalibData, RowCenter, ColCenter, XWorld, YWorld) * XWorld, YWorld 单位是 mm现在要在 XWorld2, YWorld 处画字 * 逆变换把世界坐标转回窗体像素 affine_trans_point_2d (CalibDataInv, XWorld2, YWorld, RowDisp, ColDisp) * RowDisp, ColDisp 就是 TextOutW 的坐标注意CalibDataInv是标定数据的逆变换矩阵用get_calib_dataget_calib_data_observ_pointsgen_cam_par_from_calib_data可导出。别手算——Halcon 的cam_par_to_hom_mat2d和hom_mat2d_invert是现成工具。4.2 动态跟踪 ROI 的文字用set_window_extents实现文字随 ROI 滚动当用户拖拽 ROI 时disp_message的文字会留在原地不动而外部渲染的文字必须跟着动。诀窍是不要在WM_PAINT里硬编码坐标而是把 ROI 的Row1,Col1,Row2,Col2存为成员变量在WM_PAINT中实时读取并计算偏移。// 在类中定义 struct ROIData { double row1, col1, row2, col2; bool valid false; }; ROIData mCurrentROI; // 当 ROI 改变时如用户拖拽结束更新 mCurrentROI void updateROI(double r1, double c1, double r2, double c2) { mCurrentROI {r1, c1, r2, c2, true}; // 强制重绘 RedrawWindow(hwnd, nullptr, nullptr, RDW_INVALIDATE | RDW_UPDATENOW); } // 在 HookedWndProc 的 WM_PAINT 中 if (mCurrentROI.valid) { // 计算 ROI 中心 double roiCenterX (mCurrentROI.col1 mCurrentROI.col2) / 2; double roiCenterY (mCurrentROI.row1 mCurrentROI.row2) / 2; // 映射到窗体像素 double dispX (roiCenterX - col1) * scaleX; double dispY (roiCenterY - row1) * scaleY; TextOutW(hdc, (int)dispX, (int)dispY, LROI Center, 10); }这个updateROI函数必须在 Halcon 的 ROI 回调中注册如set_callbackH_MSG_ROI_CHANGED否则文字不会动态更新。5. 避坑指南GDI 文字渲染在 Halcon 窗体上的 4 个血泪经验5.1 现象文字一闪而过只在重绘瞬间可见原因用了GetDC而非BeginPaint导致 Halcon 的WM_PAINT处理器在EndPaint后立即用BitBlt覆盖整个客户区把你画的文字冲掉。解决死守BeginPaint/EndPaint流程且return 0拦截消息。不要试图在WM_ERASEBKGND里画——它比WM_PAINT早且 Halcon 会清空。5.2 现象高分屏200% DPI下文字巨大且模糊原因GDI 默认不感知系统 DPICreateFont(-12,...)的 -12 是逻辑像素DPI 缩放后变成 -24但字体引擎没做 hinting。解决用GetDpiForWindow获取 DPI动态计算逻辑字号int dpi GetDpiForWindow(hwnd); int fontSize -MulDiv(12, dpi, 96); // 96 是默认 DPI HFONT hFont CreateFont(fontSize, ...);5.3 现象中文显示为方块或乱码原因CreateFont传了ANSI字符串如SimSun但TextOutW需要WCHAR且字体名必须用 Unicode。解决字体名必须用LMicrosoft YaHei且编译时定义UNICODE和_UNICODE或者用CreateFontIndirectLOGFONT.lfFaceName赋WCHAR数组。5.4 现象Qt 场景下文字和图像不同步闪烁原因QPainter直接画在QWindow上但 Halcon 的HWindow有自己的双缓冲机制两者刷新时机不一致。解决禁用 Halcon 的双缓冲set_window_param(hwin, buffer_mode, false)改用 Qt 的QGraphicsView::setViewportUpdateMode(QGraphicsView::FullViewportUpdate)强制同步刷新或更优解——把文字画在QGraphicsScene的QGraphicsTextItem上用QGraphicsItem::setPos()设置图像坐标由 Qt 统一管理 Z-order 和缩放。6. 进阶技巧用 GDI 实现阴影、渐变与 SVG 图标叠加让检测结果真正“看得懂”6.1 用 GDI 替代 GDI支持 Alpha 通道与路径文字GDI 的TextOutW只能画实心文字而产线需要“半透明红色警告框白色文字”这种效果。GDI 是唯一选择——它支持Graphics::DrawString的StringFormat和SolidBrush的 alpha 通道。关键步骤用Gdiplus::Graphics::FromHDC(hdc)创建 GDI 上下文用Gdiplus::Font和Gdiplus::SolidBrush(Color(128,255,0,0))创建半透明红刷用Gdiplus::StringFormat::GenericTypographic()确保字符间距精确Graphics::DrawString支持RectF区域自动换行解决热词里“halcon怎么检测一个物体是否完整”后的多行状态描述如“缺料左侧螺丝未安装”。#include gdiplus.h #pragma comment(lib, gdiplus.lib) // 在 WM_PAINT 中 Gdiplus::Graphics graphics(hdc); Gdiplus::Font font(LMicrosoft YaHei, 14, Gdiplus::FontStyleRegular, Gdiplus::UnitPixel); Gdiplus::SolidBrush brush(Gdiplus::Color(128, 255, 0, 0)); // 半透明红 Gdiplus::StringFormat format; format.SetAlignment(Gdiplus::StringAlignmentCenter); format.SetLineAlignment(Gdiplus::StringAlignmentCenter); graphics.DrawString(L缺料左侧螺丝未安装, -1, font, Gdiplus::RectF(100, 50, 200, 40), format, brush);6.2 SVG 图标叠加用Gdiplus::Graphics::DrawImage渲染矢量图标比文字更直观的是图标——比如在缺陷位置画一个⚠️SVG。Halcon 不支持 SVG但 GDI 可以用Gdiplus::Bitmap加载 SVG需第三方库如libsvg转 PNG或直接用Gdiplus::GraphicsPath手绘。我常用路径法画警告三角Gdiplus::GraphicsPath path; path.AddPolygon(points, 3); // points 是三个 PointF 构成的三角形顶点 Gdiplus::Pen pen(Gdiplus::Color(255, 255, 128, 0), 2.0f); Gdiplus::SolidBrush brush(Gdiplus::Color(255, 255, 255, 0)); graphics.DrawPath(pen, path); graphics.FillPath(brush, path);6.3 最后一条硬核经验永远用SetWindowPos控制 Z-order别信“后画的在上面”我在某汽车焊点检测项目里翻过车以为TextOutW在WM_PAINT末尾调用就一定在顶层结果被 Halcon 的set_display_font触发的内部文字覆盖。后来发现 Halcon 的disp_message其实是在WM_PAINT的最后阶段绘制比你的EndPaint还晚。终极解法是用SetWindowPos(hwnd, HWND_TOPMOST, 0,0,0,0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE)把文字层窗体置顶——但注意这会让窗体抢焦点所以必须加WS_EX_TRANSPARENT扩展样式并用SetLayeredWindowAttributes设置 alpha 通道做成真正的“透明覆盖层”。这招在“halcon浓淡补正的算法”调试时特别有用——你可以在补正前/后图像上同时叠加不同颜色文字对比。希望帮到你。本文还有配套的精品资源点击获取
企业数字化 ERP 产品动态
相关推荐
Jetson设备上YOLO与DeepStream环境搭建与优化指南 1. YOLO与DeepStream测试环境搭建
1.1 硬件准备与系统要求 在Jetson设备上部署YOLODeepStream方案,首先需要确认硬件配置。我推荐使用Jetson Xavier NX或Orin系列开发套件,这些设备具备足够的算力支撑实时目标检测。以Jetson Orin NX 16GB为例ÿ… · 2026/11/7 10:35:26
风-车-桥耦合振动分析:物理-数据双驱动模型实践 1. 项目背景与核心价值风-车-桥耦合振动问题一直是土木工程领域的经典难题。每当强风天气,我们常能看到大桥拉索剧烈摆动或桥面明显晃动的新闻画面,而行驶其上的车辆又会进一步加剧这种动力相互作用。传统研究方法往往将风荷载、车辆荷载和桥梁响应割裂分… · 2026/11/3 20:48:13
ThinkPHP查询构造器eq/egt等运算符:翻译、索引与迁移坑 接手一份放了两年多的后台代码,翻到条件数组那一行写着price > [egt, 100],旁边注释还标了一句“大于等于”。当时提问的人一直在搜“mysql egt”,因为他以为这是数据库层面的新写法,结果搜出来全是零散的关键字片段࿰… · 2026/11/7 4:30:20
考低压电工证知识考试真题与备考技巧 低压电工证考试怕不过白交培训费?内部消息告诉你怎么稳过 怕考不过白交培训费?你不是一个人。每年都有不少学员花了几千块报名培训,结果考试挂科,不仅钱打水漂,还耽误了工作机会。别急,我这有 内部消息… · 2026/11/7 10:35:05
电工证续期在线申请流程在哪考?上岗找工作别踩坑 电工证续期在线申请流程在哪考?上岗找工作别踩坑 你手上拿着电工证,但已经快到期了,现在单位急着安排你上岗,可证没续上,岗位又不能空着,这事儿可真让人头疼。别急,今天咱们就来聊聊 电工证续期在线申请流程 ,顺便告诉你 在哪考… · 2026/11/7 10:35:05
和顺县报考电工证保姆级教程:证书过期了不知道怎么复审延期 和顺县报考电工证保姆级教程:证书过期了不知道怎么复审延期 证书过期了不知道怎么复审延期?别慌,今天这份保姆级教程,帮你从0到1搞定和顺县报考电工证的复审流程,避免被处罚、影响工作,还能让证书一直有效。… · 2026/11/7 10:35:05
天津电力电缆作业证多少钱?转岗电工必须知道的避坑指南 天津电力电缆作业证多少钱?转岗电工必须知道的避坑指南 急需特种作业证才能上岗找工作,这话说得一点不假。特别是像焦作这样的工业城市,电工、焊工、高处作业等特种作业岗位门槛高、竞争激烈,手里没有【天津电力电缆作业证】,连面试资格都拿不到。现在问… · 2026/11/7 10:35:05
有ic卡电工证可以应聘电工吗真实经历告诉你答案 有ic卡电工证可以应聘电工吗真实经历告诉你答案 证书过期了不知道怎么复审延期,这是我去年在漯河市做市政工程时遇到的最头疼的问题。作为一名持证电工,证书一过期,就等于“无证上岗”,轻则被工地清退,重则面临罚款或法律追责。很多同行跟我一样,都经… · 2026/11/7 10:34:05
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:27:59
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:28:03
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/6 10:29:23
澳洲水电工证考试:证书过期了不知道怎么复审延期?电子证书怎么弄? 澳洲水电工证考试:证书过期了不知道怎么复审延期?电子证书怎么弄? 证书过期了不知道怎么复审延期?别慌,很多人在拿到【澳洲水电工证考试】的电子证书后,一不小心就忽略了复审时间,结果证书失效,工作受阻,甚至被单位追责。今天就从【澳洲水电工证考试… · 2026/11/7 0:00:41
电工作业提示版通过率揭秘:怎么考才能一次过? 电工作业提示版通过率揭秘:怎么考才能一次过? 怕考不过白交培训费?别急,今天我就从驻马店应届工程类毕业生的视角,带你全面了解电工作业提示版的考试流程、备考要点和真实通过率,帮你少走弯路、提高一次通过率。… · 2026/11/7 0:00:41
电工证年审报名千万别踩坑 外省证转过来要搞清这几点 电工证年审报名千万别踩坑 外省证转过来要搞清这几点 之前考的证在外省能不能转过来?这个问题是很多电工从业者最关心的,特别是像你这样在商丘从事公路工程的人员,经常需要跨省流动,证书的 有效性 和 可迁移性… · 2026/11/7 0:00:41
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:27:59
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:28:03
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/6 10:29:23