CListCtrl单元格编辑:VC6用CEdit/CComboBox动态实现
简介这是一份面向VC6/MFC开发者的CListCtrl表格可编辑实战资源解决在单文档应用程序中让列表控件支持单元格编辑的实际需求。资源完整演示了通过LVS_EDITLABELS风格创建可编辑CListCtrl并围绕LVN_BEGINLABELEDIT与LVN_ENDLABELEDIT消息编写响应函数实现内容校验与数据更新同时引入ControlTracker控件追踪器优化编辑过程中的选择、拖动等交互细节。压缩包共58个文件包含7个头文件、6个C源文件还有可执行程序、pdb调试符号、obj中间文件、rc资源脚本等类型Debug目录下的pdb、obj、ilk等可用于断点调试和构建过程分析ico、bmp、rc等记录了程序界面素材整体仅3.8MB结构紧凑、便于按需查阅。已有841人学习下载适合正在学习MFC控件定制、单文档架构扩展或表格交互开发的读者参考。通过对照源码与工程配置可清晰理解消息映射机制的完整流程并直接复用ControlTracker等辅助类显著缩短表格编辑功能的开发周期。1. 双击单元格就能改数据一个 VC6 单文档项目里的 CListCtrl 表格可编辑扩展做 VC6 编程的老人应该都有过这种经历单文档类扩展出来的数据录入界面列表用的是 CListCtrl用户录完发现某个单元格填错了第一反应是双击去改。但 CListCtrl 默认只能整行增删、整行替换双击除了选中行什么都做不了。大部分项目只能塞一个“编辑”按钮选中行后弹出对话框来回切窗口非常割手。这个项目解决的正是这件事在不换控件、不改数据结构的前提下给 CListCtrl 补上“表格可编辑”能力。核心思路是动态创建控件——点击单元格时在对应的矩形位置上生成一个 CEdit 或 CComboBox接管文本输入失焦、回车或 Esc 时把内容写回列表并销毁控件。整套事件处理封装在宿主类里一个头文件加一个源文件就能接入现有工程。适合还在维护 MFC 老系统、或者想在轻量界面里快速获得 Excel 式编辑体验的开发者。2. 架构与类设计用宿主类加两个临时输入控件绕开重绘噩梦2.1 为什么不重写表格三种实现路线的取舍给 CListCtrl 做单元格编辑网上能查到的方案大致有三类。第一类是直接换第三方网格控件功能完整但代价大。老工程里 CListCtrl 往往已经被多个视图引用数据通过 CImageList、LVCOLUMN、SetItemData 挂接换控件意味着所有调用点都要改而且第三方控件的配色、字体和原界面很难保持一致。第二类是 owner-draw 自绘。重写 DrawItem在选中态下画一个假的“编辑框”再拦截键盘输入自己维护光标。这个方案视觉效果最统一但实现量相当于写一个迷你文本框光处理光标闪烁、选区、IME 输入就够折腾不适合快速交付。第三类就是本项目采用的动态创建控件覆盖上去。列表本身不动点击可编辑列时CListCtrl 的派生类在单元格矩形上生成一个真正的 CEdit 或 CComboBox输入完成后取文本、SetItemText、销毁控件。对视图中任何既有逻辑透明失败回退也简单——不创建就是了。这个取舍对老项目是最小的侵入我一般也优先推荐这条路。它唯一的风险是输入控件和列表滚动、焦点管理之间的配合这部分正是后面避坑章节要展开的。2.2 类职责划分与消息流转这套实现核心只有两个类外加两个 MFC 自带的临时控件。CEditableListCtrl 是宿主类从 CListCtrl 派生。它负责三件事记录哪些列可编辑、可编辑列的类型响应 LVN_CLICK 通知把点击坐标翻译成行号列号维护当前存在的编辑控件的生命周期包括创建、提交、销毁。CEdit 和 CComboBox 是动态创建的临时控件它们的父窗口是宿主 CListCtrl。它们不承担业务逻辑只负责输入。MFC 会把 EN_KILLFOCUS 通知发送给父窗口宿主类在消息映射里接收并提交数据。视图类只需要在 OnInitialUpdate 或 OnInitDialog 里创建列表、设置列头然后调用 SetEditable 声明“第几列可以编辑”。整个调用链一句话就能说清。以下是类职责对照表类 / 对象职责对外关键方法CEditableListCtrl命中测试、编辑控件生命周期、提交回写SetEditable、StartEditCell、SetColumnTypeCEdit文本输入由宿主类动态创建处理键盘消息CComboBox下拉选择输入由宿主类动态创建下拉列表数据由外部传入CView / CDialog创建列表、填充数据列表初始化后调用 SetEditable消息流转顺序是用户在可编辑列上单击系统向父窗口发送 LVN_CLICKCEditableListCtrl 通过 ON_NOTIFY_REFLECT 把这个通知反射回自己解析 NMITEMACTIVATE 的 iRow、iCol调用 StartEditCell 创建临时控件用户输入完后回车、Esc 或点击别处触发提交宿主类取回文本写入列表行销毁控件。2.3 文件结构与接入方式整个工程只需要新增两个文件EditableListCtrl.h 和 EditableListCtrl.cpp。加上一个可选的 CComboEntry 辅助类用来承载下拉选项。接入时视图类里原本创建列表的代码不动只需要在创建完列头后追加一行声明。下面是头文件里的核心声明能看出这个类对外接口非常收敛// EditableListCtrl.h #pragma once class CEditableListCtrl : public CListCtrl { public: enum CellType { CELL_TEXT 0, // 文本编辑 CELL_COMBO, // 下拉框编辑 }; CEditableListCtrl(); // 设置某列为可编辑 // iCol: 列号(从0开始)nType: CELL_TEXT / CELL_COMBO // pOptions: 当 nTypeCELL_COMBO 时传入下拉选项 void SetEditable(int iCol, int nType CELL_TEXT, const CStringArray* pOptions NULL); // 主动触发某个单元格进入编辑状态供外部调用 void StartEditCell(int iRow, int iCol); protected: struct COLINFO { int nType; // 列类型 CStringArray arOptions; // 下拉选项 }; CMapint, int, COLINFO*, COLINFO* m_mapCols; // 列配置表 int m_iEditRow; // 当前编辑中的行 int m_iEditCol; // 当前编辑中的列 CEdit* m_pEdit; // 当前活动编辑框 CComboBox* m_pCombo; // 当前活动下拉框 void CommitEdit(); // 提交并销毁当前编辑控件 void CancelEdit(); // 取消并销毁当前编辑控件 void GetCellRect(int iRow, int iCol, CRect rcCell); // 下面这些是 MFC 消息处理函数 afx_msg void OnLvnClick(NMHDR* pNMHDR, LRESULT* pResult); afx_msg void OnEditKillFocus(); afx_msg void OnComboKillFocus(); afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); afx_msg void OnSize(UINT nType, int cx, int cy); virtual BOOL PreTranslateMessage(MSG* pMsg); };调用方式简洁直接在视图类的 OnInitialUpdate 里创建完列表和列头之后加上m_listCtrl.SetEditable(1, CEditableListCtrl::CELL_TEXT); // 第1列文本可编辑 m_listCtrl.SetEditable(2, CEditableListCtrl::CELL_COMBO, options); // 第2列下拉可编辑SetEditable的作用是把列配置塞进m_mapCols后续点击事件会查询这张表决定是否进入编辑。m_mapCols用CMap而不是数组是因为列号不一定从 0 连续递增如果只是固定第 1、2 列也可以直接用数组。3. 核心实现从鼠标点击到编辑框创建、提交、销毁的完整链路3.1 命中测试把点击转换成可编辑单元格进入编辑状态的第一步是判断用户点在了哪一行、哪一列。CListCtrl 会在鼠标单击时发送 LVN_CLICK 通知携带一个 NMITEMACTIVATE 结构。这里的关键是把iItem和iSubItem解析干净。需要特别提醒一点只有当列表设置了 LVS_EX_FULLROWSELECT 扩展风格时iSubItem才会准确返回非 0 列的信息。否则点击第二列时通知里拿到的 iItem 可能是 -1。所以视图创建列表时要先设置这个扩展风格。代码如下void CEditableListCtrl::OnLvnClick(NMHDR* pNMHDR, LRESULT* pResult) { NMITEMACTIVATE* pActivate (NMITEMACTIVATE*)pNMHDR; *pResult 0; // 空白区域点击、或者点击了第0列(通常是序号列)不进入编辑 if (pActivate-iItem 0 || pActivate-iSubItem 0) return; // 查询列配置没有配置说明该列不可编辑 COLINFO* pInfo NULL; if (!m_mapCols.Lookup(pActivate-iSubItem, pInfo)) return; // 保证目标行是可见的否则编辑框会定位到窗口外面 EnsureVisible(pActivate-iItem, TRUE); StartEditCell(pActivate-iItem, pActivate-iSubItem); }NMITEMACTIVATE的iItem是行索引iSubItem是列索引。第 0 列跳过编辑是刻意留的口子通常表格里的第 0 列放序号或状态图标强行编辑反而会让用户困惑。EnsureVisible这一步很重要用户通过滚动条把目标行滚到可视区外时如果还按原坐标创建编辑框控件会被创建到列表窗口之外看起来就像“点了没反应”。3.2 创建编辑控件位置、字体、焦点全部要对齐确定目标单元格后下一步是拿到该单元格的屏幕矩形然后在这个矩形范围内创建 CEdit 或 CComboBox。VC6 的 CListCtrl 没有现成的 GetSubItemRect 成员函数需要通过 LVM_GETSUBITEMRECT 消息获取。这个窗口消息的用法有点怪矩形变量的 top 和 left 两个字段在发送前要分别填入行号和列号发送成功后传出真实的像素矩形。这也是 VC6 编程里被问过很多次的经典传参方式。void CEditableListCtrl::GetCellRect(int iRow, int iCol, CRect rcCell) { // 入参top 填行号left 填列号 rcCell.top iRow; rcCell.left iCol; // 该消息会改写 rcCell 为实际的客户区坐标矩形 ::SendMessage(m_hWnd, LVM_GETSUBITEMRECT, (WPARAM)GetParent()-GetSafeHwnd(), (LPARAM)rcCell); }拿到矩形之后创建编辑控件的代码写在StartEditCell里。一开始写这个函数的时候没做“上一次编辑未提交”的兜底连续快速点击两个不同单元格项目里会出现两个编辑框同时存在的乱象。后来在函数入口先CancelEdit一次把上一个残留控件清理干净才消停。void CEditableListCtrl::StartEditCell(int iRow, int iCol) { // 如果上一次编辑控件还在先按提交处理 if (m_pEdit || m_pCombo) CommitEdit(); COLINFO* pInfo NULL; if (!m_mapCols.Lookup(iCol, pInfo)) return; CRect rcCell; GetCellRect(iRow, iCol, rcCell); // 把矩形向内缩2像素避免编辑框边框和列表网格线重叠 rcCell.DeflateRect(2, 2); m_iEditRow iRow; m_iEditCol iCol; CString strText GetItemText(iRow, iCol); if (pInfo-nType CELL_COMBO) { m_pCombo new CComboBox(); m_pCombo-Create(WS_CHILD | WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST | WS_VSCROLL, rcCell, this, 0x6001); // 下拉框选项从列配置里填充 for (int i 0; i pInfo-arOptions.GetSize(); i) m_pCombo-AddString(pInfo-arOptions[i]); m_pCombo-SetFont(GetFont()); // 当前单元格已有值时选中对应项 m_pCombo-SelectString(-1, strText); m_pCombo-SetFocus(); } else { m_pEdit new CEdit(); m_pEdit-Create(WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER | ES_AUTOHSCROLL, rcCell, this, 0x6002); m_pEdit-SetFont(GetFont()); // 字体必须和列表一致 m_pEdit-SetWindowText(strText); m_pEdit-SetFocus(); // 全选原文本用户直接输入就能覆盖 m_pEdit-SetSel(0, -1); } }几个参数值得单独说明。0x6001 和 0x6002 是临时控件的 ID宿主类在消息映射里靠它们区分 EN_KILLFOCUS 通知来源。父窗口this传给 Create 时必须保证是 CListCtrl 本身而不是视图否则子控件的通知消息会走视图的消息映射宿主类收不到。ES_AUTOHSCROLL让文本编辑框在内容超出列宽时自动横向滚动不回行。CBS_DROPDOWNLIST保持下拉框收起避免展开的下拉列表把界面撑乱。3.3 提交与销毁输入结束后的三路出口编辑控件的生命周期结束有三种出口用户点击了列表其他地方编辑框失焦用户按回车确认用户按 Esc 取消。后两个要靠重写 PreTranslateMessage 捕获第一个靠 EN_KILLFOCUS。提交的核心函数是CommitEdit。这里有个新手很容易踩的坑先销毁控件再去 GetWindowText取到的一定是空字符串。必须先取文本、写回列表再销毁。void CEditableListCtrl::CommitEdit() { // 文本类编辑控件 if (m_pEdit ::IsWindow(m_pEdit-GetSafeHwnd())) { CString strValue; m_pEdit-GetWindowText(strValue); // 第一步取文本 SetItemText(m_iEditRow, m_iEditCol, strValue); // 第二步写回列表 m_pEdit-DestroyWindow(); // 第三步销毁窗口 delete m_pEdit; // 第四步释放对象 m_pEdit NULL; } // 下拉框类编辑控件处理方式相同 if (m_pCombo ::IsWindow(m_pCombo-GetSafeHwnd())) { int nIndex m_pCombo-GetCurSel(); CString strValue; if (nIndex ! CB_ERR) m_pCombo-GetLBText(nIndex, strValue); SetItemText(m_iEditRow, m_iEditCol, strValue); m_pCombo-DestroyWindow(); delete m_pCombo; m_pCombo NULL; } }CancelEdit和CommitEdit结构一致只是不取文本直接销毁这里不再重复贴代码。销毁后必须把指针置 NULL否则动态创建的窗口在 OnKillFocus 回调里会反复触发提交逻辑。键盘出口通过重写 PreTranslateMessage 拦截。因为消息会先经过焦点窗口的 PreTranslateMessage再向上传递到父窗口所以即使焦点在子编辑框里宿主类也能拦到BOOL CEditableListCtrl::PreTranslateMessage(MSG* pMsg) { // 只有消息目标是当前编辑控件时才处理 if (pMsg-hwnd m_pEdit-GetSafeHwnd() || pMsg-hwnd m_pCombo-GetSafeHwnd()) { if (pMsg-message WM_KEYDOWN) { switch (pMsg-wParam) { case VK_RETURN: CommitEdit(); // 回车确认 return TRUE; // 不继续下发消息 case VK_ESCAPE: CancelEdit(); // Esc 取消 return TRUE; } } } return CListCtrl::PreTranslateMessage(pMsg); }回车和 Esc 在文本框里原本都有默认行为回车可能触发父窗口的默认按钮Esc 可能触发系统菜单。这里拦截后直接吞掉消息保证编辑流程完全可控。判断pMsg-hwnd而不是GetFocus()是为了防止输入法窗口或下拉列表子窗口抢走焦点判断。3.4 滚动、列宽与删行外部状态变化时的同步单元格编辑最容易被忽略的场景是用户正在输入却按下了滚动条或者拖动了列分隔线。列表内容滚动了可编辑框还是创建时那个位置会出现“控件漂在别的行上”的诡异效果。处理策略是不尝试移动编辑框而是先提交再销毁。滚动这种强交互状态没必要维持正在输入的上下文反而会给自己惹麻烦。void CEditableListCtrl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { // 横向滚动必然导致列偏移先提交当前编辑 if (m_pEdit || m_pCombo) CommitEdit(); CListCtrl::OnHScroll(nSBCode, nPos, pScrollBar); } void CEditableListCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { if (m_pEdit || m_pCombo) CommitEdit(); CListCtrl::OnVScroll(nSBCode, nPos, pScrollBar); }列表的 WM_SIZE 也做同样处理窗口尺寸变化时列的显示位置必然变化编辑框跟着销毁是最省事的方案。删除行、全选清空这些操作在视图层触发前调用一次 CommitEdit 即可。这样外部操作永远只会看到一个状态要么编辑框存在并且位置正确要么根本不存在。4. 避坑记录单元格编辑最常见的 5 个翻车现场与排查办法4.1 编辑框出现后立刻消失像是闪了一下现象单击可编辑单元格编辑框刚显示出来马上就不见了。如果仔细看能看到边框闪一下。原因这是单击和双击的竞争问题。CListCtrl 的 LVN_CLICK 和 LVN_DBLCLK 是两条独立通知。用户双击时第一次点击触发创建编辑框第二次点击因为编辑框已经覆盖在单元格上点击位置落在编辑框内编辑框立刻失去焦点EN_KILLFOCUS 触发了提交销毁。所以看到的“闪一下”其实是编辑框完成了从创建到销毁的完整生命周期。解决在消息映射里也加上 LVN_DBLCLK 的处理。双击时第二次点击的 LVN_CLICK 里 iItem 值不会变可以记录一个时间戳或标志在 OnLvnClick 开头检查是否刚处理过同一行的编辑如果是则跳过。更简单的做法是编辑框创建后设置一次焦点失焦提交前判断焦点是否是编辑框本身如果焦点没动过就不提交。我当时直接用了一个 300 毫秒的临界判断双击时只有第一次进入编辑第二次被忽略。4.2 滚动列表后编辑框留在原地数据却跟着列表跑了现象正在编辑某一行拖动垂直滚动条列表行滚上去了但编辑框还停留在原来的像素位置感觉像文本框悬浮在列表上。原因CListCtrl 客户区的行坐标在滚动后会整体重排编辑框是子窗口坐标是基于客户区的绝对像素不会跟着某个行移动。解决在 OnVScroll 和 OnHScroll 里提交销毁这是最稳的。有人尝试在滚动时用 LVM_GETTOPINDEX 重新定位编辑框位置做出来也能用但代价是编辑框频繁移动会闪烁用户正在输入时文本跳动很恼人。不如滚动即提交改完再下去点一次就是了。4.3 回车键提交失效焦点跑到视图的某个按钮上现象在编辑框里按回车数据没有提交界面上的某个默认按钮反而被触发了或者焦点直接转移到其他控件。原因回车键是对话框和单文档视图里最容易被“瓜分”的键。视图的加速键表、默认按钮逻辑会在 PreTranslateMessage 的父窗口链上截获回车消息。我的实现是在宿主类的 PreTranslateMessage 里拦截但宿主类的 PreTranslateMessage 执行顺序取决于焦点窗口链如果视图类重写了 PreTranslateMessage 且没有先调用基类宿主类的拦截就失效。解决在接收焦点的那一层也就是视图或对话框的 PreTranslateMessage 里转发优先判断。判断目标窗口是否是宿主类里的编辑框如果是把消息重新发送给宿主类的编辑框窗口保证回车能被处理到BOOL CMyView::PreTranslateMessage(MSG* pMsg) { if (pMsg-message WM_KEYDOWN pMsg-wParam VK_RETURN m_listCtrl.IsEditing()) { // 把回车直接发给编辑框走 CEdit 自己的翻译链 ::SendMessage(pMsg-hwnd, WM_KEYDOWN, VK_RETURN, pMsg-lParam); return TRUE; } return CView::PreTranslateMessage(pMsg); }这只是其中一个方案核心原则是不要让回车消息在到达编辑框之前被视图的加速键逻辑消耗掉。4.4 整行高亮背景下编辑框里的文字看不清现象点击第二列开始编辑编辑框创建了但背景是选区蓝色或黑色里面的文字和光标看不清。原因CListCtrl 设置过 LVS_EX_FULLROWSELECT 后点击任意列都会选中整行系统绘制选中状态时会把整行背景刷成高亮色。动态创建的 CEdit 默认背景是白色但文字绘制时父窗口的选中态背景透过编辑框边缘缝隙显示出来看起来就是白底黑字里夹着一块深色背景。解决点击进入编辑前先用 SetItemState 把当前选中行取消选中把编辑框的父窗口背景刷成白色或者在宿主类的 OnCtlColor 里拦截编辑框的背景画刷返回白色。最省事的是在 StartEditCell 里加上一句SetItemState(m_iEditRow, 0, LVIS_SELECTED);选中态去掉后单元格底色恢复正常编辑框白底也干净了。代价是编辑结束后行不再高亮但数据写回后如果需要可以恢复选中态。4.5 退出视图时野指针崩溃或者内存泄漏现象关闭单文档视图时程序异常退出崩溃点往往在 CEdit 的销毁流程里不崩溃的话用内存检测工具能看到动态创建的 CEdit 对象泄漏。原因CommitEdit只在正常的编辑闭环里调用。如果用户在输入过程中直接关闭窗口、切换视图编辑框窗口和宿主类一起被销毁但动态 new 出来的 CEdit 对象没有走delete析构函数不会执行野指针悬在消息映射里下次访问就崩。解决在宿主类的 OnDestroy 里兜底清理void CEditableListCtrl::OnDestroy() { // 销毁视图时强制丢弃未提交的编辑控件 if (m_pEdit ::IsWindow(m_pEdit-GetSafeHwnd())) { m_pEdit-DestroyWindow(); delete m_pEdit; m_pEdit NULL; } if (m_pCombo ::IsWindow(m_pCombo-GetSafeHwnd())) { m_pCombo-DestroyWindow(); delete m_pCombo; m_pCombo NULL; } CListCtrl::OnDestroy(); }从这里得到的血泪教训是所有动态创建的控件必须有一个统一的“销毁出口”。要么 Commit要么 Cancel要么窗口销毁时兜底三选一绝不能裸 new 不负责。5. 二次开发把文本编辑扩展成下拉框、数字校验和多行控件5.1 增加下拉框列类型上文已经看到 CELL_COMBO 的雏形。再往前走一步下拉框的数据来源应该从外部传入而不是在宿主类里写死。合理的做法是让 SetEditable 的第三个参数做成CStringArray每个单元格可以在进入编辑前临时替换选项数组。比如“状态”列下拉框里是“未开始、进行中、已完成”直接传入即可。要让下拉框在编辑状态下展开可以在创建后发一条 CB_SHOWDROPDOWN 消息m_pCombo-ShowDropDown(TRUE);这样用户点进去直接看到选项列表省一次点击。5.2 提交时按列做输入校验表格可编辑的终极需求通常是“能改但别乱改”。在 CommitEdit 里按列类型做规则检查即可。比如某列是数量要求数字某列是日期要求格式正确。校验失败时不清空编辑框也不销毁控件而是弹提示后把焦点还回去if (pInfo-nType CELL_TEXT pInfo-nMask COL_FLAG_NUMBER) { if (!IsNumeric(strValue)) { MessageBox(请输入数字, 输入错误, MB_ICONWARNING | MB_OK); m_pEdit-SetFocus(); return; // 不提交也不销毁 } }思路是列配置里加一个掩码字段SetEditable同时接收掩码提交函数里根据掩码走校验分支。这样外部调用不用改只是扩展参数而已。5.3 多行文本与更多自定义控件遇到长文本列CEdit 可以改成 ES_MULTILINE 样式编辑框高度拉大文本换行显示。不过列表行高固定多行编辑框会覆盖住下方几行这个体验不太理想。更好的做法是保留单行编辑提交后单元格文本放不下时用 ToolTip 展示全文。这套架构里宿主类对输入控件的类型没有写死只要有窗口句柄就可以扩展。后续改成日期选择控件、数字调节框只需要在 StartEditCell 里加一个创建分支并在 CommitEdit 里按 ID 分流取数据即可。从那以后我每次给 CListCtrl 加这种动态控件都会强制走一遍“创建-编辑-提交-销毁”的闭环验证确认单击、双击、滚动、关闭视图四条路径都不会留下野生编辑框。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

Unity加载OpenDrive高精地图:从解析到车辆循迹仿真全攻略

Unity加载OpenDrive高精地图:从解析到车辆循迹仿真全攻略

简介:面向自动驾驶仿真与虚拟测试场景的Unity道路生成器工程,主要服务于C#开发者、环境仿真工程师以及AD算法研究人员。项目核心基于标准OpenDRIVE文件格式,解析道路几何、车道与交叉口等描述信息,并借助EasyRoads3D工具集在Unity…

2026/10/18 13:20:56 阅读更多 →
快递包裹自动识别检测算法落地实践:基于YOLO26从数据到边缘部署

快递包裹自动识别检测算法落地实践:基于YOLO26从数据到边缘部署

做快递包裹自动识别检测,最难的点往往不是模型结构本身,而是让它在真实分拣线上那种光线忽明忽暗、包裹互相挤压、胶带反光的现场里稳定工作。这段时间我配合一个物流自动分拣项目,把基于 YOLO26 的快递包裹自动识别检测算法从数据集构建一路…

2026/10/18 13:20:56 阅读更多 →
巨量算数X-Bogus、_signature、msToken三参数加密逻辑解析

巨量算数X-Bogus、_signature、msToken三参数加密逻辑解析

简介:本资源聚焦巨量算数平台核心安全参数(X-Bogus、_signature、msToken)的加密机制逆向分析与工程化复现,面向爬虫开发者、Web安全研究员及逆向初学者,解决高频 encountered 的参数动态生成与请求鉴权绕过难题。压缩…

2026/10/18 13:20:56 阅读更多 →

最新新闻

HTML/CSS智能补全:语义化编码与前端效率革命

HTML/CSS智能补全:语义化编码与前端效率革命

1. 这不是“快捷键教学”&#xff0c;而是前端效率革命的起点你有没有过这样的时刻&#xff1a;写HTML时&#xff0c;手在键盘上敲了十几遍<div class"container">&#xff0c;光是闭合标签就反复按了三次方向键&#xff1b;写CSS时&#xff0c;想加个margin: …

2026/10/18 14:07:20 阅读更多 →
WebView Cookie丢失与跨域登录态不同步:排查思路与修复实践

WebView Cookie丢失与跨域登录态不同步:排查思路与修复实践

做移动端开发这几年&#xff0c;WebView 里 Cookie 丢失是我踩过最频繁的坑之一。用户明明在原生页面登录成功&#xff0c;一跳到 H5 页面又打回原形&#xff1b;同一个域名下接口访问正常&#xff0c;换个域名就完全拿不到会话&#xff1b;甚至同一个 WebView 里前后两个页面&…

2026/10/18 14:07:20 阅读更多 →
Spring Boot社区助老志愿者服务平台:毕设架构与跑通指南

Spring Boot社区助老志愿者服务平台:毕设架构与跑通指南

简介&#xff1a;基于SpringBoot的社区助老志愿者服务平台毕业设计项目&#xff0c;面向计算机相关专业学生与需要快速搭建完整毕设方案的开发者。系统采用Java语言与SpringBoot框架&#xff0c;围绕志愿者服务、老人信息管理等核心功能展开&#xff0c;涵盖需求分析、系统结构…

2026/10/18 14:07:20 阅读更多 →
基于YOLOv8的安全帽与反光衣检测:数据、训练到部署全流程实战

基于YOLOv8的安全帽与反光衣检测:数据、训练到部署全流程实战

工地安全监管这事&#xff0c;我一直觉得是个典型的“看着简单、做好了很难”的落地场景。这两年YOLO系列模型迭代速度飞快&#xff0c;尤其是YOLOv8出来之后&#xff0c;做安全帽检测的方案在网上已经满天飞。但真要把“安全帽反光衣检测”做成一个拿得出手、能实际跑起来的项…

2026/10/18 14:07:20 阅读更多 →
基于YOLOv26的变电站变压器设备检测与智能巡检实践

基于YOLOv26的变电站变压器设备检测与智能巡检实践

在电力巡检这个圈子里摸爬滚打了几年&#xff0c;我越来越觉得&#xff0c;目标检测模型换了一代又一代&#xff0c;直到YOLOv26出来之后&#xff0c;才算真正把变电站变压器设备检测与识别这件事做得比较舒服。今天就跟大家聊聊&#xff0c;我是怎么基于YOLOv26做了一套完整的…

2026/10/18 14:07:20 阅读更多 →
ERP问卷集成总对不上字段?2026我试了五款谁对接更稳当些

ERP问卷集成总对不上字段?2026我试了五款谁对接更稳当些

[本文为个人项目选型实测记录&#xff0c;所有工具均自行注册体验&#xff0c;无任何厂商合作&#xff0c;内容仅作为技术选型参考。]背景上个月薪酬模块上线&#xff0c;HR要求把员工满意度问卷的部门和职级字段直接同步进ERP人事档案。结果头一批数据导进去&#xff0c;部门I…

2026/10/18 14:06:19 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型&#xff08;GMM&#xff09;的语音识别系统&#xff0c;很多人第一反应就是一堆数学公式&#xff0c;觉得门槛很高。但如果你真的在MATLAB里把它落地跑通&#xff0c;会发现核心其实就是三件事&#xff1a;把声音变成特征向量&#xff0c;用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人&#xff0c;但落到具体操作上&#xff0c;无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程&#xff1a;对图像做反白、改调色板、彩色转灰度&#xff0c;最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型&#xff08;GMM&#xff09;的语音识别系统&#xff0c;很多人第一反应就是一堆数学公式&#xff0c;觉得门槛很高。但如果你真的在MATLAB里把它落地跑通&#xff0c;会发现核心其实就是三件事&#xff1a;把声音变成特征向量&#xff0c;用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人&#xff0c;但落到具体操作上&#xff0c;无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程&#xff1a;对图像做反白、改调色板、彩色转灰度&#xff0c;最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →