简介这是一份面向Qt中级开发者与Windows桌面应用进阶实践者的完整技术实现方案聚焦于突破Qt默认窗口限制打造高度集成Windows原生特性的无边框窗口。资源通过Qt与Windows API深度协同系统性解决了图标显示、鼠标拖拽、自由缩放、Aero阴影、最大化/最小化控制及DWM模糊背景等核心问题适用于开发专业级浏览器外壳、轻量级IDE或定制化系统工具等场景。压缩包共48个文件含13个头文件.h与12个源码文件.cpp构成主体逻辑9个PNG图标与1个ICO确保视觉一致性2个UI界面文件和1个QRC资源文件支撑界面组织辅以PRO工程配置、PRI模块依赖及CSS样式定义整体仅73KB结构精炼、即拿即用。已有1269人学习下载提供可直接编译运行的完整工程涵盖BorderlessWindow主窗口、QWinHost跨平台封装、Web组件集成及多状态按钮资源是理解Qt窗口机制与Windows底层消息交互的优质实操范例。1. QT做无边框窗口不是“去掉QFrame”就完事AERO阴影、任务栏缩略图、Snap吸附、系统级拖拽全链路实测你肯定试过setWindowFlags(Qt::FramelessWindowHint)然后发现——窗口真没了边框但也彻底丢了系统级能力拖不动、点不中最大化按钮、AltTab里缩略图是黑的、Win←→无法自动贴边、鼠标移到标题栏区域毫无反应。这不是QT的锅是绕过了Windows窗口管理器DWM的底层契约。这份资源不是教你怎么“画个假标题栏”而是用WINAPI直连DWM和USER32让QT窗口在系统眼里就是个原生AERO风格窗口能响应WM_NCHITTEST、能调DwmEnableBlurBehindWindow、能拦截WM_GETMINMAXINFO控制缩放边界、能注册SetWindowPos触发任务栏预览更新。适合正在做桌面端产品化交付的QT开发者尤其当你被测试同学指着说“这个窗口没法用WinD显示桌面”“拖到屏幕边缘没反应”时这篇就是你的后悔药。它不依赖第三方库所有WINAPI调用都封装进QWidget子类C11语法VS2019MinGW8.1双环境验证过。2. 从WM_NCHITTEST开始为什么你的无边框窗口拖不动真相是系统根本没把鼠标当“标题栏”2.1 系统如何判断鼠标该干啥WM_NCHITTEST消息的底层逻辑Windows对每个鼠标事件都会先发一个WM_NCHITTEST消息给窗口询问“这个坐标点你希望我当成什么区域处理”返回值决定行为HTCAPTION表示标题栏允许拖拽、HTMAXBUTTON表示最大化按钮点击触发最大化、HTMINBUTTON表示最小化按钮。默认Qt::FramelessWindowHint下QT直接返回HTCLIENT客户区系统就认为“这地方只能画画不能动窗”。所以第一步必须重载nativeEvent捕获并重写这个消息bool AeroFramelessWidget::nativeEvent(const QByteArray eventType, void *message, long *result) { if (eventType windows_generic_MSG) { MSG *msg static_castMSG*(message); if (msg-message WM_NCHITTEST) { const QPoint pos this-mapFromGlobal(QPoint(msg-lParam 0xFFFF, (msg-lParam 16) 0xFFFF)); *result hitTest(pos); return true; } } return QWidget::nativeEvent(eventType, message, result); }提示nativeEvent是QT接入原生消息的唯一入口别试图用winEvent已废弃或eventFilter收不到WM_NCHITTEST。*result必须赋值否则系统按默认逻辑走你的重写就失效了。2.2 hitTest函数四行代码定义可拖拽区域与按钮热区hitTest函数是核心逻辑它根据鼠标坐标返回系统期望的HT常量。这里我们定义顶部25像素为标题栏区域支持拖拽右上角24×24像素为关闭按钮中间两个24×24为最小化/最大化按钮LRESULT AeroFramelessWidget::hitTest(const QPoint pos) { const QRect topBarRect(0, 0, width(), 25); // 标题栏高度25px const QRect closeRect(width() - 24, 0, 24, 24); const QRect maxRect(width() - 48, 0, 24, 24); const QRect minRect(width() - 72, 0, 24, 24); if (topBarRect.contains(pos)) { if (closeRect.contains(pos)) return HTCLOSE; if (maxRect.contains(pos)) return HTMAXBUTTON; if (minRect.contains(pos)) return HTMINBUTTON; return HTCAPTION; // 其他顶部区域视为标题栏拖拽 } // 四周留出8px边框用于缩放Win10默认行为 if (pos.x() 8 pos.y() 25) return HTLEFT; if (pos.x() width() - 8 pos.y() 25) return HTRIGHT; if (pos.y() 25) return HTTOP; if (pos.y() height() - 8) return HTBOTTOM; if (pos.x() 8 pos.y() 25) return HTTOPLEFT; if (pos.x() width() - 8 pos.y() 25) return HTTOPRIGHT; if (pos.x() 8 pos.y() height() - 8) return HTBOTTOMLEFT; if (pos.x() width() - 8 pos.y() height() - 8) return HTBOTTOMRIGHT; return HTCLIENT; // 其余区域为普通客户区 }关键参数说明HTCAPTION触发窗口拖拽系统会自动锁定鼠标并移动窗口无需自己实现mouseMoveEventHTLEFT/HTTOP/HTBOTTOMRIGHT等触发系统级缩放Windows会自动绘制缩放光标、限制缩放比例、处理多屏DPI适配返回HTCLIENT的区域QT的mousePressEvent才会被触发适合放自定义按钮2.3 让按钮真正生效必须手动处理WM_SYSCOMMAND仅返回HTCLOSE还不够。系统收到HTCLOSE后会向窗口发送WM_SYSCOMMAND消息携带SC_CLOSE参数。但QT默认不处理这个消息所以点击关闭按钮没反应。必须在nativeEvent中捕获并转发if (msg-message WM_SYSCOMMAND) { switch (msg-wParam) { case SC_CLOSE: this-close(); *result 0; return true; case SC_MINIMIZE: this-showMinimized(); *result 0; return true; case SC_MAXIMIZE: this-showMaximized(); *result 0; return true; case SC_RESTORE: this-showNormal(); *result 0; return true; } }注意SC_RESTORE在窗口最大化后点击还原按钮时触发不是SC_MAXIMIZE的反向操作。很多开发者漏掉这个导致最大化后再点标题栏无法还原。3. AERO毛玻璃与阴影DwmEnableBlurBehindWindow不是开个开关那么简单3.1 毛玻璃效果的三个硬性前提DWM毛玻璃Blur Behind不是调个API就行它有三个系统级约束窗口必须启用DWM合成Win7默认开启但若用户禁用AERO主题如高对比度模式DwmIsCompositionEnabled会返回FALSE窗口不能是顶层无焦点窗口WS_EX_LAYERED或WS_EX_TRANSPARENT会导致毛玻璃失效背景必须是纯色或渐变如果窗口背景是图片或复杂控件毛玻璃会显示为灰色噪点。验证是否可用BOOL isDwmEnabled FALSE; DwmIsCompositionEnabled(isDwmEnabled); if (!isDwmEnabled) { qWarning() DWM composition disabled, blur effect unavailable; return; }3.2 正确设置BlurBehind结构体字段一个都不能错DWM_BLURBEHIND结构体有四个字段其中fEnable和hRgnBlur是关键fTransitionOnMaximized控制最大化时是否保持模糊设为TRUE更符合AERO体验void AeroFramelessWidget::enableBlurBehind() { DWM_BLURBEHIND bb {0}; bb.dwFlags DWM_BB_ENABLE | DWM_BB_BLURREGION | DWM_BB_TRANSITIONONMAXIMIZED; bb.fEnable TRUE; bb.hRgnBlur NULL; // 设为NULL表示整个客户区模糊 bb.fTransitionOnMaximized TRUE; HRESULT hr DwmEnableBlurBehindWindow((HWND)this-winId(), bb); if (FAILED(hr)) { qWarning() DwmEnableBlurBehindWindow failed: hr; } }提示hRgnBlur若传入自定义HRGN区域句柄可实现局部模糊如只模糊标题栏下方内容区但需用CreateRectRgn创建并确保坐标系是屏幕坐标且窗口移动后需重新设置。3.3 阴影不是CSSDwmSetWindowAttribute控制真实系统阴影Windows 10的窗口阴影由DWM管理不是QT样式表能控制的。必须调用DwmSetWindowAttribute启用DWMWA_USE_IMMERSIVE_DARK_MODE影响标题栏文字颜色和DWMWA_CAPTION_COLOR影响阴影强度// 启用深色模式兼容避免白色文字在浅色标题栏上不可读 BOOL darkMode TRUE; DwmSetWindowAttribute((HWND)this-winId(), DWMWA_USE_IMMERSIVE_DARK_MODE, darkMode, sizeof(darkMode)); // 设置标题栏背景色间接影响阴影深度RGB值越暗阴影越重 COLORREF captionColor RGB(30, 30, 30); DwmSetWindowAttribute((HWND)this-winId(), DWMWA_CAPTION_COLOR, captionColor, sizeof(captionColor));常见误区很多人以为DWMWA_BORDER_COLOR能改阴影色其实它只影响窗口边框无边框窗口无效。真正控制阴影的是DWMWA_CAPTION_COLOR——系统根据此颜色计算阴影扩散和透明度。4. Snap贴边与多屏缩放WM_GETMINMAXINFO不是摆设是系统缩放的宪法4.1 Snap吸附的底层机制系统在拖拽时实时查询窗口尺寸建议当你把窗口拖到屏幕边缘Windows会发送WM_GETMINMAXINFO消息要求窗口返回MINMAXINFO结构体其中ptMaxSize、ptMaxPosition、ptMinTrackSize字段告诉系统“我最大能多大”、“我应该出现在哪”、“我最小能缩多小”。如果不处理系统按默认逻辑通常为屏幕尺寸处理导致Snap失效或缩放错位。if (msg-message WM_GETMINMAXINFO) { MINMAXINFO *mminfo reinterpret_castMINMAXINFO*(msg-lParam); const QRect screenRect QGuiApplication::primaryScreen()-geometry(); // Snap贴边当窗口宽度接近屏幕宽度时强制设为全屏宽度 if (width() screenRect.width() * 0.9) { mminfo-ptMaxSize.x screenRect.width(); mminfo-ptMaxSize.y screenRect.height(); mminfo-ptMaxPosition.x 0; mminfo-ptMaxPosition.y 0; } else { // 非全屏状态最大尺寸为屏幕尺寸减去任务栏 mminfo-ptMaxSize.x screenRect.width(); mminfo-ptMaxSize.y screenRect.height() - getTaskbarHeight(); // 需自行实现 } // 最小可拖拽尺寸防止缩得太小无法操作 mminfo-ptMinTrackSize.x 320; mminfo-ptMinTrackSize.y 240; return true; }4.2 多屏DPI适配GetDpiForWindow获取当前屏幕DPI在4K屏1080P副屏混合环境下窗口跨屏移动时系统可能以错误DPI渲染。必须在WM_DPICHANGED消息中响应并调整窗口大小if (msg-message WM_DPICHANGED) { const UINT dpi HIWORD(msg-wParam); const QRect newRect *reinterpret_castQRect*(msg-lParam); // 按DPI缩放窗口内容如字体、图标 this-setDevicePixelRatio(qreal(dpi) / 96.0); // 调整窗口位置和大小以匹配新DPI区域 this-setGeometry(newRect); this-update(); // 强制重绘 }血泪经验WM_DPICHANGED在窗口创建时不会触发必须在show()后手动调用一次GetDpiForWindow获取初始DPI否则首次显示在高DPI屏上会模糊。4.3 任务栏缩略图黑屏DwmInvalidateIconicBitmaps强制刷新无边框窗口常出现AltTab缩略图是黑的、任务栏预览空白的问题。原因是DWM缓存了窗口位图而无边框窗口的绘制流程可能未触发缓存更新。解决方案是在窗口激活、大小改变、内容更新后调用void AeroFramelessWidget::onWindowContentChanged() { // 告诉DWM这张缩略图过期了请重新抓取 DwmInvalidateIconicBitmaps((HWND)this-winId()); }调用时机建议resizeEvent结束时paintEvent绘制完成后showNormal()/showMaximized()之后5. 避坑指南六个真实翻车现场与血泪修复方案5.1 现象窗口最大化后标题栏按钮消失点击区域失灵原因hitTest函数在最大化状态下未适配窗口尺寸变化。最大化后width()/height()变为屏幕尺寸但按钮热区坐标仍按原始尺寸计算导致closeRect.contains(pos)永远为false。解决在changeEvent中监听QEvent::WindowStateChange当窗口状态变为Qt::WindowMaximized时动态重置按钮热区坐标或改用相对坐标如width()*0.95而非绝对像素。5.2 现象毛玻璃效果在Win11上显示为纯黑Win10正常原因Win11默认启用DWMWA_SYSTEMBACKDROP_TYPE会覆盖DWM_BLURBEHIND。DwmEnableBlurBehindWindow在Win11上已被标记为deprecated。解决检测系统版本Win11改用DwmSetWindowAttribute设置DWMWA_SYSTEMBACKDROP_TYPE为DWMSBT_MAINWINDOWif (QSysInfo::windowsVersion() QSysInfo::WV_WINDOWS11) { DWORD backdropType DWMSBT_MAINWINDOW; DwmSetWindowAttribute((HWND)this-winId(), DWMWA_SYSTEMBACKDROP_TYPE, backdropType, sizeof(backdropType)); }5.3 现象拖拽窗口时鼠标卡顿CPU占用飙升原因nativeEvent中频繁调用mapFromGlobal和contains在高刷屏144Hz下每秒触发上百次WM_NCHITTESTQRect::contains内部有浮点运算开销。解决缓存QRect对象避免每次重建用整数坐标比较替代contains如pos.x() closeX pos.x() closeX24 pos.y() 24添加简单距离阈值离标题栏远时直接返回HTCLIENT跳过计算。5.4 现象多屏环境下Snap到副屏右侧时窗口被切掉一半原因WM_GETMINMAXINFO中使用的QGuiApplication::primaryScreen()始终返回主屏未根据窗口当前位置获取所属屏幕。解决用QGuiApplication::screenAt(this-geometry().center())获取当前窗口中心点所在屏幕再取其geometry()作为screenRect。5.5 现象启用毛玻璃后QWidget子控件如QPushButton文字发虚、边缘锯齿原因DWM毛玻璃与QT的设备像素比devicePixelRatio冲突控件未按实际DPI缩放。解决在enableBlurBehind后立即调用this-setDevicePixelRatio(this-devicePixelRatio())强制重同步对关键控件按钮、标签设置setAttribute(Qt::WA_TranslucentBackground)并手动绘制背景。6. 进阶技巧用SetWindowPos实现无闪烁窗口状态切换与任务栏图标同步6.1 为什么showMaximized()会有1帧闪烁QT的showMaximized()本质是先show()再setGeometry(screenRect)中间存在一个短暂的非最大化状态DWM会捕捉到这一帧并生成错误缩略图。真正的无闪烁最大化必须绕过QT的几何管理直接调用WINAPIvoid AeroFramelessWidget::smoothMaximize() { HWND hwnd (HWND)this-winId(); RECT screenRect; SystemParametersInfo(SPI_GETWORKAREA, 0, screenRect, 0); // 获取工作区排除任务栏 // 直接设置窗口位置和大小不经过QT事件循环 SetWindowPos(hwnd, HWND_NOTOPMOST, screenRect.left, screenRect.top, screenRect.right - screenRect.left, screenRect.bottom - screenRect.top, SWP_SHOWWINDOW | SWP_FRAMECHANGED); // 强制通知任务栏更新预览 ITaskbarList3 *pTaskbar nullptr; if (SUCCEEDED(CoCreateInstance(__uuidof(TaskbarList), nullptr, CLSCTX_INPROC_SERVER, __uuidof(ITaskbarList3), (void**)pTaskbar))) { pTaskbar-MarkFullscreenWindow(hwnd, TRUE); pTaskbar-Release(); } }6.2 任务栏图标状态同步ITaskbarList3接口详解仅靠showMinimized()无法让任务栏图标进入“最小化”高亮态。必须使用ITaskbarList3的MarkFullscreenWindow控制全屏态和SetProgressValue控制进度条但最关键的同步是ThumbBarAddButtons——为缩略图添加自定义按钮如播放/暂停// 为任务栏缩略图添加两个按钮 THUMBBUTTON buttons[2] {0}; buttons[0].dwMask THB_BITMAP | THB_TOOLTIP | THB_FLAGS; buttons[0].iId 1; buttons[0].iBitmap 0; // 使用内置图标 buttons[0].szTip LPlay; buttons[0].dwFlags THBF_ENABLED; buttons[1].dwMask THB_BITMAP | THB_TOOLTIP | THB_FLAGS; buttons[1].iId 2; buttons[1].iBitmap 0; buttons[1].szTip LPause; buttons[1].dwFlags THBF_DISABLED; ITaskbarList3 *pTaskbar nullptr; if (SUCCEEDED(CoCreateInstance(__uuidof(TaskbarList), nullptr, CLSCTX_INPROC_SERVER, __uuidof(ITaskbarList3), (void**)pTaskbar))) { pTaskbar-ThumbBarAddButtons(hwnd, 2, buttons); pTaskbar-Release(); }注意ITaskbarList3需要链接shell32.lib并在.pro文件中添加LIBS -lshell32。按钮IDiId在后续WM_COMMAND消息中通过wParam低16位获取用于响应点击。6.3 一个必须养成的习惯窗口销毁前释放DWM资源很多开发者忽略资源清理导致程序退出后DWM残留模糊效果影响其他应用。在析构函数中必须显式关闭BlurAeroFramelessWidget::~AeroFramelessWidget() { if (this-winId()) { HWND hwnd (HWND)this-winId(); // 关闭毛玻璃 DWM_BLURBEHIND bb {0}; bb.dwFlags DWM_BB_ENABLE; bb.fEnable FALSE; DwmEnableBlurBehindWindow(hwnd, bb); // 清理任务栏缩略图按钮 ITaskbarList3 *pTaskbar nullptr; if (SUCCEEDED(CoCreateInstance(__uuidof(TaskbarList), nullptr, CLSCTX_INPROC_SERVER, __uuidof(ITaskbarList3), (void**)pTaskbar))) { pTaskbar-ThumbBarDismissButtons(hwnd); pTaskbar-Release(); } } }从那以后我每次写无边框窗口第一件事就是打开nativeEvent模板把WM_NCHITTEST、WM_SYSCOMMAND、WM_GETMINMAXINFO三个消息的骨架先码好再填业务逻辑。宁可多写十行WINAPI也不信“QT样式表能搞定一切”的玄学。毕竟用户不管你是用QSS还是DirectX他们只看——拖得到底顺不顺点关机按钮是不是真关了Win←是不是乖乖贴左半边屏幕。希望帮到你。本文还有配套的精品资源点击获取
企业数字化 ERP 产品动态
相关推荐
AARRR模型拆解:从流量焦虑到增长闭环的底层逻辑与实操 1. 拆解AARRR模型:从流量焦虑到增长闭环的底层逻辑做增长的人都有一个共同的痛点:流量越来越贵,用户越来越难留,老板天天盯着ROI问为什么投放没效果。我接触过不少团队,一上来就砸预算买量,结果新增用户曲线… · 2026/11/14 23:14:12
AARRR模型拆解:从五个字母到增长操作系统 1. 拆解AARRR模型:从五个字母到一套增长操作系统第一次接触AARRR模型是在一个用户增长项目里,当时团队正为一个新产品上线后的数据表现发愁——注册量看着还行,但付费转化始终起不来,大家各说各话,有人怪渠道质量差&am… · 2026/11/14 23:14:12
互动墙面技术:提升展厅沉浸感的核心方案 1. 项目概述:墙面互动装置如何提升展厅沉浸感在当代展厅设计中,单面墙的互动装置已成为营造沉浸式体验的关键载体。不同于传统展墙的静态展示,这种技术驱动的互动墙面通过多模态交互、动态反馈和空间叙事重构,能够将观众从被动接受… · 2026/11/3 21:34:55
职业学校的中级电工证怎么报名和外省证能否转过来 职业学校的中级电工证怎么报名和外省证能否转过来 之前考的证在外省能不能转过来?这个问题很多电工朋友都问过,特别是那些在外地打工、后来返乡发展的朋友。其实,职业学校的中级电工证和其他特种作业证一样,虽然在外地考了,但只要符合规定,是可以… · 2026/11/14 23:13:17
电工证 职称评定报名入口与办理流程 良心建议 电工证 职称评定报名入口与办理流程 良心建议 怕考不过白交培训费?这年头,谁还没点证书焦虑?尤其像 电工证 这种关系到安全和职业发展的特种作业证,一旦考不过,培训费、时间成本全打了水漂。今天就从一个在周口项目现场做安全管理员的角度,… · 2026/11/14 23:13:17
电工证哪个部门发的好保姆级教程 电工证哪个部门发的好保姆级教程 实操考试心里没底怕挂科?电工证哪个部门发的好?这可能是很多从业者的第一个问题,尤其是在备考或准备报考的时候。电工证作为特种作业操作证的重要一环,直接影响着你能否持证上岗。本文将从真实从业者角度出发,带你看清电… · 2026/11/14 23:13:17
张桂军电工证怎么考才稳?实操考试心里没底怕挂科 张桂军电工证怎么考才稳?实操考试心里没底怕挂科 实操考试心里没底怕挂科?张桂军电工证的含金量不仅体现在证书本身,更在于它在实际工作中带来的职业保障与风险规避能力。尤其是在建筑工地,电工证的缺失可能导致严重的安全事故,甚至承担法律责任。因此,… · 2026/11/14 23:13:17
电工证复审需要原件?工地太忙根本没时间复习考试,上岗必备怎么应对 电工证复审需要原件?工地太忙根本没时间复习考试,上岗必备怎么应对 工地太忙根本没时间复习考试,尤其是那些刚从其他行业转岗过来的新乡电工,一边要应对紧张的工期,一边还要为电工证复审做准备,压力山大。很多人以为只要拿着电工证就可以安心上岗,其实… · 2026/11/14 23:12:16
电工证丢失还能补吗?千万别踩坑,丢了证等于失业 电工证丢失还能补吗?千万别踩坑,丢了证等于失业 你正在找工作,但手里的电工证突然丢了,这下怎么办?别急,先别慌, 电工证丢失还能补吗 ?答案是肯定的,但 千万别踩坑 ,补办流程如果不了解,可能会耽误你上岗、甚至影响到你的收入。… · 2026/11/14 23:07:54
电力电缆作业证直播报名入口与办理流程良心建议 电力电缆作业证直播报名入口与办理流程良心建议 你是不是也担心学历不高报不了名?别急,今天就给你讲讲 电力电缆作业证直播 的报名流程和那些你必须知道的干货, 良心建议 在这里,别错过。 电力电缆作业证直播报名需要什么条件?… · 2026/11/14 13:23:47
英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑 英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑 怕考不过白交培训费?英德电工证报考费多少钱,你真的了解吗?现在市面上培训机构五花八门,价格参差不齐,很多人一不小心就花了冤枉钱,结果还考不过。别急,今天就来给你说清楚英德电工证的… · 2026/11/14 13:20:59
有初级电工证怎么工作 2026河南最新政策怎么应对 有初级电工证怎么工作 2026河南最新政策怎么应对 之前考的证在外省能不能转过来?这个问题我每天被问上百次。2026年河南最新政策对证书跨省转移有了明确说明,特别是南阳市的从业者,需要特别关注。… · 2026/11/14 0:00:31
电工证过期了不知道怎么复审?考电工证自学书+官方报名入口全攻略 电工证过期了不知道怎么复审?考电工证自学书+官方报名入口全攻略 证书过期了不知道怎么复审延期?很多人遇到这种情况,要么是工作太忙没时间处理,要么是不知道具体流程,导致证书失效,影响工作和项目进展。其实复审并不难,关键是要找准官方报名入口,掌… · 2026/11/14 0:00:31
为什么要低压电工证实操考试考什么 为什么低压电工证值不值得考?别再被中介骗了 你是不是也经常看到网上有人在问“低压电工证到底值不值得考”?或者在找报名点时,担心被中间人骗钱?这些问题,我懂,我也经历过。作为一名在应急管理行业摸爬滚打多年的从业者,我深知低压电工证不仅是一个从… · 2026/11/14 0:00:31
双极步进电机控制实战: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/13 6:12:21
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/13 6:11:51
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/13 22:31:30