windows需先设ws_popup无边框再加ws_ex_layered扩展样式,macos用nspanel配setopaque:no和clearcolor,linux依赖x11合成器及argb32视觉,跨平台应分条件实现而非抽象统一窗口类。

Windows 上用 SetWindowLong + WS_EX_LAYERED 控制无边框与透明
Windows 原生实现悬浮窗的核心是窗口样式和分层属性。必须先去掉标题栏和边框:SetWindowLong(hwnd, GWL_STYLE, WS_POPUP | WS_VISIBLE),再启用分层支持:SetLayeredWindowAttributes(hwnd, 0, 128, LWA_ALPHA)(128 是半透)。注意:如果漏掉 WS_EX_LAYERED 扩展样式(用 SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED) 补上),SetLayeredWindowAttributes 会静默失败,窗口不透明也不报错。
常见错误是把 WS_POPUP 和 WS_OVERLAPPEDWINDOW 混用,后者自带边框,覆盖掉前者;还有在 WM_CREATE 之前就调用透明设置,此时窗口句柄无效。
macOS 上用 NSPanel + setOpaque: 和 setHasShadow:
macOS 没有“无边框透明窗口”的单一 API,得组合控制:NSPanel 比 NSWindow 更适合悬浮场景(默认忽略 Dock、不参与 Mission Control);关键三步:调用 [panel setOpaque:NO] 关闭背景绘制,[panel setBackgroundColor:[NSColor clearColor]] 确保内容区透明,再用 [panel setHasShadow:NO] 去掉阴影(否则透明时阴影仍可见)。漏掉 setOpaque:NO 会导致窗口强制重绘为不透明灰块,哪怕背景色设成 clear 也无效。
注意:必须在 makeKeyAndOrderFront: 之前完成这些设置,运行时修改 opaque 属性不会刷新渲染;另外,macOS 对透明窗口的鼠标事件默认穿透,需显式设置 [panel setIgnoresMouseEvents:NO] 才能响应点击。
Linux(X11)用 _NET_WM_WINDOW_TYPE_DOCK + Composite 扩展
X11 下没有统一的“透明窗口”概念,依赖合成器(Compositor)支持。基础做法是:创建普通窗口后,通过 XChangeProperty 设置 _NET_WM_WINDOW_TYPE 为 _NET_WM_WINDOW_TYPE_DOCK(让窗口被桌面环境识别为面板类,减少干扰),再用 XRender 扩展设置 ARGB32 视觉(XMatchVisualInfo 查找支持 alpha 的 visual),最后调用 XSetWindowBackgroundPixmap 或直接用 Cairo 绘制带 alpha 的 surface。若合成器未开启(如 i3 默认关),窗口会变成纯黑或纯白——这不是代码错,而是环境缺失。
容易踩的坑:直接用 OverrideRedirect=True 虽能去边框,但会丢失所有窗口管理器功能(无法置顶、拖动失效);正确姿势是保留 OverrideRedirect=False,靠 _NET_WM_WINDOW_TYPE 和合成器协同控制行为。
跨平台封装建议:避免抽象窗口类,优先用条件编译 + 小型胶水层
强行写一个 TransparentWindow 抽象基类,反而会让每个平台的特殊逻辑(比如 macOS 的 runloop 交互、X11 的 visual 匹配)变得难调试。更可行的是定义统一接口(如 show()、setAlpha(float)、setPosition(int x, int y)),内部用 #ifdef _WIN32 / #ifdef __APPLE__ / #ifdef __linux__ 分支实现。例如 setAlpha 在 Windows 调 SetLayeredWindowAttributes,macOS 调 [NSView setAlphaValue:],X11 则重新绘制整个 Cairo surface。
字体渲染、鼠标捕获、DPI 缩放这些细节在各平台差异极大,不要指望一次封装全适配;真正跨平台的关键不是“一套代码跑三家”,而是“同一套业务逻辑,只换三小段平台相关 glue code”。透明度值范围(0–255 vs 0.0–1.0)、坐标系原点(左上 vs 左下)、事件循环集成方式,都是上线前必须逐个对齐的点。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











