MFC自绘CTabCtrl实战:从默认灰控件到可换肤标签页

简介:这份资源是一套自绘 CTabCtrl 控件的完整实现代码,面向具备 MFC 基础、希望突破系统默认控件外观限制的 Windows 开发者。它解决的是标准标签页控件样式单一、难以适配个性化界面需求的问题,通过手动接管绘制流程,让开发者能够自由定制标签的颜色、形状、字体与边框,并加入滑动、淡入淡出等过渡动画以及图标支持,从而提升界面的辨识度与交互质感。压缩包共 2 个文件,包含 1 个 cpp 实现文件与 1 个 h 头文件,整体约 6KB,其中头文件声明类结构与成员,实现文件则集中处理 OnPaint 等消息,借助 GDI/GDI+ 完成线条、矩形与文本绘制,并可能结合定时器驱动动画帧计算。目前已有 360 人学习,适合想深入理解自定义控件绘制机制、研究非客户区处理与动画逻辑的开发者参考借鉴。

1. 自绘 CTabCtrl:从默认灰控件到可换肤标签页的那一步

MFC 里做界面,绕不开CTabCtrl。默认样式就是 Win95 味道的灰色凸起标签,放在今天任何一套 UI 里都显得突兀。很多做工业软件、上位机、医疗设备界面的同行,产品功能都做完了,最后卡在标签页太丑这一关。自绘CTabCtrl就是解决这个问题的:不改动 MFC 框架,不引入第三方库,通过接管WM_DRAWITEM或重写DrawItem,把标签的绘制权拿到自己手里,想画成什么样就画成什么样。

这份资源适合两类人:一是正在用 MFC 做桌面端、被默认控件外观拖后腿的开发者;二是想理解 Windows 自绘机制、但不想啃大部头框架源码的进阶新手。它不涉及复杂算法,核心就是消息映射和 GDI 绘制,但坑不少,下面按实际落地顺序拆开讲。

2. 自绘 CTabCtrl 的三种技术路线:选错了后面全是返工

2.1 为什么默认 CTabCtrl 不能直接改颜色

CTabCtrl封装的是 Win32 的SysTabControl32窗口类。这个系统控件在WM_PAINT里自己画标签,外部拿不到绘制上下文。你调SetBkColor、SetTextColor基本无效,因为系统控件不响应这些消息。想改外观,只有两条路:要么让系统控件把绘制任务交出来,要么完全自己画一个。

常见做法是重写DrawItem虚函数。CTabCtrl继承自CWnd,而CWnd提供了DrawItem虚函数,当控件收到WM_DRAWITEM时会调用它。但这里有个前提:控件必须设置TCS_OWNERDRAWFIXED样式,否则系统不会发WM_DRAWITEM。很多人第一步就翻车,样式没加,重写了DrawItem死活不进来。

// 在对话框的 OnInitDialog 里,给 Tab 控件加自绘样式 m_tabCtrl.ModifyStyle(0, TCS_OWNERDRAWFIXED); // 注意:ModifyStyle 之后需要重新设置控件大小或调用 SetWindowPos // 否则样式变更可能不触发重绘 m_tabCtrl.SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);

ModifyStyle的第二个参数是新增样式,TCS_OWNERDRAWFIXED告诉系统“标签绘制我自己来”。SWP_FRAMECHANGED强制窗口重新计算非客户区,确保样式生效。这一步不做,后面所有绘制代码都是白写。

2.2 方案对比:DrawItem 重写 vs 完全自绘 vs 子类化

三条路线各有适用场景,选之前先看清楚代价。

方案改动量可控粒度适用场景主要风险
重写 DrawItem小标签整体只换标签外观,保留系统行为样式未生效、坐标算错
完全自绘 CWnd大像素级需要异形标签、动画要自己处理所有鼠标消息
子类化 + NM_CUSTOMDRAW中部分绘制阶段微调颜色、字体阶段理解错导致画两遍

我一般推荐先走DrawItem路线。它能保留CTabCtrl的页管理、键盘导航、TCN_SELCHANGE通知这些现成逻辑,只把绘制换掉。完全自绘适合标签形状完全不像传统 Tab 的场景,比如弧形、斜切、带图标的卡片式标签,但代价是InsertItem、DeleteItem、SetCurSel这些都要自己实现,工作量翻倍。

子类化加NM_CUSTOMDRAW是另一条路,但CTabCtrl对NM_CUSTOMDRAW的支持不如ListCtrl完整,很多绘制阶段拿不到,实际用起来反而更绕。除非你只想改文字颜色,否则不建议。

2.3 消息映射与 DrawItem 的触发条件

DrawItem的签名是virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)。DRAWITEMSTRUCT里关键字段有四个:hDC是绘制设备上下文,rcItem是当前标签的矩形区域,itemID是标签索引,itemState是状态位(选中、焦点、禁用)。

void CMyTabCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { CDC dc; dc.Attach(lpDrawItemStruct->hDC); int nIndex = lpDrawItemStruct->itemID; CRect rcItem = lpDrawItemStruct->rcItem; bool bSelected = (lpDrawItemStruct->itemState & ODS_SELECTED) != 0; // 根据选中状态选不同背景色 COLORREF clrBg = bSelected ? RGB(255, 255, 255) : RGB(230, 230, 230); dc.FillSolidRect(&rcItem, clrBg); // 取标签文字 CString strText; TCHAR szBuf[256] = { 0 }; TCITEM tci = { 0 }; tci.mask = TCIF_TEXT; tci.pszText = szBuf; tci.cchTextMax = 255; GetItem(nIndex, &tci); strText = szBuf; // 文字颜色随选中状态变化 dc.SetTextColor(bSelected ? RGB(0, 120, 215) : RGB(80, 80, 80)); dc.SetBkMode(TRANSPARENT); dc.DrawText(strText, &rcItem, DT_CENTER | DT_VCENTER | DT_SINGLELINE); dc.Detach(); }

dc.Attach把系统传进来的 HDC 绑到 MFC 的 CDC 对象上,用完必须Detach,否则 CDC 析构时会释放这个 HDC,导致系统后续绘制崩溃。这是血泪经验,很多人第一次写自绘就栽在这里,程序跑起来看着正常,一切换标签就花屏。

GetItem取文字时,TCITEM的pszText必须指向有效缓冲区,cchTextMax要设对。如果标签文字超过 255 字符,这里会截断,需要动态分配。一般标签不会那么长,但心里要有数。

itemState里ODS_SELECTED表示当前选中标签。注意,CTabCtrl的选中标签和焦点标签可能不是同一个,键盘操作时焦点在某个标签上但选中项没变,这时候ODS_FOCUS会置位。如果你要画焦点虚线框,得单独处理。

3. 把标签画好看:颜色、字体、图标与圆角的参数化实现

3.1 选中态与未选中态的视觉分层

默认控件最丑的地方是选中标签和未选中标签几乎没区别,就靠一个凸起边框区分。自绘时要拉开层次:选中标签背景用亮色、文字用主色、底部加一条高亮线;未选中标签背景用浅灰、文字用次级灰。这样一眼就能看出当前在哪一页。

// 选中标签底部画一条 2px 高亮线 if (bSelected) { CRect rcLine = rcItem; rcLine.top = rcLine.bottom - 2; dc.FillSolidRect(&rcLine, RGB(0, 120, 215)); } // 未选中标签右侧画一条细分隔线 else { CRect rcSep = rcItem; rcSep.left = rcSep.right - 1; rcSep.top += 6; rcSep.bottom -= 6; dc.FillSolidRect(&rcSep, RGB(200, 200, 200)); }

高亮线宽度一般 2 到 3 像素,太细看不清,太粗显得笨重。分隔线上下各留 6 像素内缩,避免顶满整个高度,视觉上更透气。这些数值不是固定的,跟标签高度有关,标签高 30 像素左右时这套参数比较协调。

3.2 字体设置与文字居中偏移

DrawItem里用的字体默认继承控件字体,但自绘时经常需要单独设。比如选中标签加粗、未选中常规。注意DRAWITEMSTRUCT的hDC里已经选入了控件字体,你要换字体得先保存旧字体,画完恢复。

CFont fontSelected, fontNormal; fontSelected.CreatePointFont(90, _T("Microsoft YaHei")); fontNormal.CreatePointFont(90, _T("Microsoft YaHei")); CFont* pOldFont = NULL; if (bSelected) { fontSelected.GetLogFont(&lf); lf.lfWeight = FW_BOLD; fontSelected.DeleteObject(); fontSelected.CreateFontIndirect(&lf); pOldFont = dc.SelectObject(&fontSelected); } else { pOldFont = dc.SelectObject(&fontNormal); } // ... 绘制文字 ... dc.SelectObject(pOldFont); // 恢复旧字体

CreatePointFont的第一个参数是字体大小的十分之一,90 表示 9 磅。lfWeight设FW_BOLD实现加粗。这里有个坑:CFont对象如果重复Create而不先DeleteObject,会泄漏 GDI 对象。GDI 对象总数有上限(默认 10000),标签页多、切换频繁时,泄漏几十次就可能让整个程序绘制异常。所以字体对象最好在控件初始化时创建一次,DrawItem里只做SelectObject,不要每次重画都新建。

文字居中用DT_CENTER | DT_VCENTER | DT_SINGLELINE。如果标签带图标,图标和文字要并排,就得手动算偏移:先取图标尺寸,算出图标加间距加文字总宽,再算起始 x 坐标。

3.3 图标与文字混排的坐标计算

带图标的标签,TCITEM的mask要加TCIF_IMAGE,iImage是图标索引。绘制时先画图标再画文字,两者整体居中。

// 假设图标 16x16,图标与文字间距 6px int nIconSize = 16; int nGap = 6; CSize szText = dc.GetTextExtent(strText); int nTotalW = nIconSize + nGap + szText.cx; int nStartX = rcItem.left + (rcItem.Width() - nTotalW) / 2; int nIconY = rcItem.top + (rcItem.Height() - nIconSize) / 2; // 画图标(m_imgList 是 CImageList 成员) if (nImageIndex >= 0) { m_imgList.Draw(&dc, nImageIndex, CPoint(nStartX, nIconY), ILD_TRANSPARENT); } // 画文字 CRect rcText = rcItem; rcText.left = nStartX + nIconSize + nGap; dc.DrawText(strText, &rcText, DT_LEFT | DT_VCENTER | DT_SINGLELINE);

GetTextExtent返回文字像素宽高,用来算总宽。ILD_TRANSPARENT让图标背景透明,否则图标会带一块底色。图标列表要在控件初始化时Create好并SetImageList,DrawItem里只负责画。

坐标计算里最容易错的是rcItem的坐标系。DRAWITEMSTRUCT给的rcItem是相对于控件客户区的,不是屏幕坐标,也不是对话框坐标。直接用就行,不要做ScreenToClient之类的转换,转了反而错位。

3.4 圆角与边框:用 CRgn 裁剪出圆角矩形

想要圆角标签,GDI 没有现成的FillRoundRect,得用RoundRect或者CRgn裁剪。RoundRect画出来边缘有锯齿,CRgn配合CDC::SelectClipRgn更平滑。

CRgn rgn; rgn.CreateRoundRectRgn(rcItem.left, rcItem.top, rcItem.right + 1, rcItem.bottom + 1, 8, 8); dc.SelectClipRgn(&rgn); dc.FillSolidRect(&rcItem, clrBg); dc.SelectClipRgn(NULL); // 恢复裁剪区

CreateRoundRectRgn的宽高参数是圆角椭圆的直径,8 表示圆角半径 4 像素。注意right和bottom要加 1,否则最右列和最下行画不到。SelectClipRgn(NULL)恢复默认裁剪区,不恢复的话后续绘制全被限制在这个圆角区域内。

圆角标签有个视觉问题:相邻标签的圆角会互相“咬”。解决办法是选中标签圆角大一点,未选中标签圆角小一点,或者只在选中标签上用圆角,未选中用直角,形成对比。

4. 避坑与排查:自绘 CTabCtrl 最常见的五个翻车点

4.1 重写 DrawItem 不触发

现象:编译通过,运行后标签还是系统默认样子,DrawItem里的断点根本不进。

原因:控件没有TCS_OWNERDRAWFIXED样式,系统不会发WM_DRAWITEM。

解决:在OnInitDialog里ModifyStyle(0, TCS_OWNERDRAWFIXED),然后SetWindowPos带SWP_FRAMECHANGED强制刷新。如果控件是动态创建的,在Create时直接加样式更省事。

4.2 切换标签后花屏或残影

现象:点另一个标签,原来标签的文字或背景残留,新标签画上去叠在一起。

原因:DrawItem里没有先擦除背景,或者dc.Detach没调用导致 HDC 状态混乱。

解决:每次绘制开头用FillSolidRect把rcItem填满,不要依赖系统擦背景。dc.Attach和dc.Detach必须成对,中间不要return跳过Detach。如果用了SelectClipRgn,画完必须SelectClipRgn(NULL)。

4.3 文字被截断或偏移

现象:标签文字显示不全,或者偏左偏右不居中。

原因:rcItem直接传给DrawText时,矩形边界和文字实际宽度不匹配;或者DT_VCENTER没配合DT_SINGLELINE使用。

解决:DrawText必须同时带DT_SINGLELINE | DT_VCENTER,少一个垂直居中就失效。如果文字还是偏,检查GetItem取文字时cchTextMax是否够大,以及TCITEM结构体是否清零(memset或= {0}),未初始化的字段可能导致GetItem行为异常。

4.4 GDI 对象泄漏导致绘制逐渐变慢

现象:程序跑一段时间后,标签切换越来越卡,最后整个窗口不刷新。

原因:DrawItem里每次新建CFont、CPen、CBrush但没有DeleteObject,GDI 对象数达到进程上限。

解决:把字体、画笔、画刷作为控件成员变量,在OnInitDialog或PreSubclassWindow里创建一次,DrawItem里只SelectObject和恢复。用任务管理器加 GDI 对象列,观察数值是否持续上涨,涨了就是泄漏。

4.5 高 DPI 下标签模糊或错位

现象:在 125% 或 150% 缩放下,标签文字发虚,图标和文字对不齐。

原因:坐标和尺寸用了硬编码像素值,没有按 DPI 缩放。

解决:用GetDpiForWindow取当前 DPI,所有尺寸乘以dpi / 96.0。字体用CreatePointFont而不是CreateFont指定像素高,点值会自动随 DPI 缩放。图标列表用SetImageList时指定ILD_SCALE或提供多倍图。

5. 进阶:把自绘 CTabCtrl 做成可复用组件的三个习惯

5.1 颜色和尺寸抽成结构体,别散落在 DrawItem 里

自绘代码写多了,最怕改一个颜色翻遍整个函数。我一般定义一个TabStyle结构体,把所有可调参数集中管理。

struct TabStyle { COLORREF clrBgNormal; COLORREF clrBgSelected; COLORREF clrTextNormal; COLORREF clrTextSelected; COLORREF clrIndicator; int nIndicatorHeight; int nCornerRadius; int nIconSize; int nIconGap; CString strFontName; int nFontSize; };

DrawItem里只读这个结构体,不写死任何数值。换皮肤时改结构体成员,重新绘制即可。这样同一套自绘逻辑可以给多个项目用,只换配置。

5.2 用内存 DC 双缓冲消除闪烁

标签切换频繁时,直接画到屏幕 DC 会闪。标准做法是先在内存 DC 里画好整张图,再一次性BitBlt到屏幕。

CDC memDC; memDC.CreateCompatibleDC(&dc); CBitmap bmp; bmp.CreateCompatibleBitmap(&dc, rcItem.Width(), rcItem.Height()); CBitmap* pOldBmp = memDC.SelectObject(&bmp); // 在 memDC 里完成所有绘制 memDC.FillSolidRect(0, 0, rcItem.Width(), rcItem.Height(), clrBg); // ... 画文字、图标、圆角 ... // 一次性贴到屏幕 dc.BitBlt(rcItem.left, rcItem.top, rcItem.Width(), rcItem.Height(), &memDC, 0, 0, SRCCOPY); memDC.SelectObject(pOldBmp);

内存 DC 的坐标系原点在rcItem左上角,所以绘制时坐标要减去rcItem.left和rcItem.top。这个转换容易忘,忘了就画到区域外面去了。双缓冲会增加内存占用,但标签区域通常不大,代价可以接受。

5.3 验证自绘效果是否正确的检查清单

写完自绘代码,别只看静态截图。按下面几步走一遍,能发现大部分隐藏问题:

检查项操作预期
选中切换依次点击每个标签高亮线跟随移动,无残影
键盘导航Ctrl+Tab 切换焦点框正确显示
动态增删运行时 InsertItem/DeleteItem标签重新布局,不崩溃
高 DPI系统缩放调到 150%文字清晰,图标对齐
长时间运行反复切换 100 次GDI 对象数稳定

GDI 对象数在任务管理器里加一列就能看。稳定不涨,说明资源管理没问题。涨了,回去查DrawItem里有没有漏掉的DeleteObject。

从那以后我每次写完自绘控件,都强制走一遍这个清单,尤其是 GDI 对象数那一项。看起来麻烦,但比上线后用户反馈“用久了就卡”要省事得多。希望帮到你。

本文还有配套的精品资源,点击获取

相关新闻

DeepSeek 实战指南:数据清洗、分析与自动化避坑手册

DeepSeek 实战指南:数据清洗、分析与自动化避坑手册

简介:这份资源是面向AI工具初学者与办公效率提升人群的DeepSeek使用教学文档,帮助读者快速掌握这款智能数据搜索与分析平台的核心操作。内容覆盖注册登录、数据导入清洗、分析可视化、文本生成与摘要、情感分析、语言翻译、任务自动化、工作流优化以及模…

2026/10/20 13:32:30 阅读更多 →
手机IDE实战:中文定制版如何用AI修Bug跑通Android开发

手机IDE实战:中文定制版如何用AI修Bug跑通Android开发

说真的,在手机上写代码这件事,我没少被人笑话。直到有一次外出没有电脑,客户半夜丢来一个紧急Bug,我硬是掏出手机,用一款装了IDE的安卓设备花了二十分钟把问题改完、编译、装到另一台手机上验证通过。从那以后我就明白…

2026/10/20 13:32:30 阅读更多 →
OpenCV图像金字塔详解:上采样、下采样与高斯差分实践

OpenCV图像金字塔详解:上采样、下采样与高斯差分实践

做图像处理的人,大概都会和“金字塔”打交道——不是埃及那种,是图像金字塔。围绕它展开的上采样、下采样和高斯差分(DoG),几乎是所有多尺度算法的地基。目标检测要在不同尺寸下找目标,图像融合要在不同频段…

2026/10/20 13:32:30 阅读更多 →

最新新闻

这6个底层技能,比学一堆工具更不容易过时

这6个底层技能,比学一堆工具更不容易过时

这6个“常用技能”,我一开始全理解错了。当时看项目标题“分享6个最常用的skill”,我第一反应是准备一份技术栈清单,甚至把某段时间特别火的几类工具关键词都列了出来。但和朋友聊完、又翻了几次项目正文之后才发现,真正的核心不是…

2026/10/20 17:34:07 阅读更多 →
工业控制系统安全工程师(CISP-ICSSE)全解析:报考条件、知识体系与职业价值

工业控制系统安全工程师(CISP-ICSSE)全解析:报考条件、知识体系与职业价值

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

2026/10/20 17:34:07 阅读更多 →
Ruby重构机票电商平台:事务、缓存与高并发实战解析

Ruby重构机票电商平台:事务、缓存与高并发实战解析

简介:eyoo旅游机票电商平台重构版是一份基于Ruby技术栈的在线机票销售系统学习资源,适合希望掌握Ruby on Rails电商项目完整开发流程的开发者,用于研究业务建模、数据库关联、接口设计与部署方案。压缩包大小约2.62MB,当前标注文件…

2026/10/20 17:34:07 阅读更多 →
AI论文写作软件怎么用?专科生毕业论文从选题到答辩的实用指南

AI论文写作软件怎么用?专科生毕业论文从选题到答辩的实用指南

如果你现在手机相册里至少存了五张“学霸同款2026 TOP10 AI论文写作软件推荐图”,但论文还卡在“题目改了四遍都没定下来”,那这篇内容就是为你准备的。我不打算继续报一遍软件名字,因为真正决定你论文能不能顺利过关的,从来不是榜…

2026/10/20 17:34:07 阅读更多 →
2024最新Node.js下载安装与环境变量配置完整指南

2024最新Node.js下载安装与环境变量配置完整指南

如果你在前端、后端或者全栈开发这条路上待过一段时间,Node.js这个名字一定绕不开。它本质上是一个基于V8引擎的JavaScript运行时,把原本只能在浏览器里跑的JavaScript带到了操作系统层面。装上它之后,你可以用JavaScript写命令行工具、写后端…

2026/10/20 17:34:07 阅读更多 →
Ubuntu下PostgreSQL安装配置与Navicat连接指南

Ubuntu下PostgreSQL安装配置与Navicat连接指南

做后端开发或者数据相关工作的朋友,应该都经历过这么一幕:好不容易在 Ubuntu 上把 PostgreSQL 装好了,却发现命令行操作没问题,客户端工具却怎么都连不上;或者反过来,Navicat 装好了,连接时报一…

2026/10/20 17:33:06 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

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

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

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

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

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

2026/10/20 1:01:30 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 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/20 10:02:08 阅读更多 →
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/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练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/20 9:50:45 阅读更多 →