主要需求:书签,快速seek,字幕,点击字幕查词。
为何不用potplayer?太卡,技术看不上,竟然保存同时设置和二进制图片文件到ini文件或注册表,一点不绿色。
播放组件,得的到的有三种:
- MFPlayer,官方框架但解码器较少。
- VLCPlayer,首次启动较慢。
- 迅雷播放组件,闭源,存在BUG。最近试出一个导黑屏死机的BUG,复现三次。seek快但是不精准。
整合这些到一个应用。
可以切换核心的视频播放器见过吗。
然后界面,选duilib,站原生。
WODPlayer 控件简史
- 2022年集成了MFPlayer、VLCPlayer、迅雷Player,各有优缺点
- 控件有进度条、底部按钮,最初用魔改的wine代码实现,分别是trackbar.c和tabbar.c。
- 2023 年重构,实现插件接口,分出动态链接库项目,扩展后可以接上任何播放器组件。
- 替换窗口控件为无窗口自绘控件。进度条很简单,用gdi+绘制两个条一个圆,记得开启平滑画笔,再绘制些简单的阴影。
- 时间进度条用定时器同步。
- 原生按钮效果也不难,背景绘制一个淡蓝色方块和边框,前景绘制图标,点击、悬浮于按钮时,改变方块色、边框色,偏移前景图标,复刻原生外观。
- 按钮点击事件仍然通过发送WM_COMMAND处理,装作原生控件。数字id在resource.h中手动指定然后写在布局xml里。
WODPlayer 无边框镂空窗口的曲折之路
不建议制作无边框窗口,坑太多。
但 WODPlayer 必须要无边框,因为有个需求,想让界面部分镂空:
为什么 WODPlayer 需要部分镂空
image (8).png如果不镂空,那么视频两边出现黑边。
一旦开启系统级别的反色滤镜,黑边立马变成白边,非常刺目。
image (5).png最大化和全屏尤为明显。
windows 平台半透明或镂空窗口(layered)有以下特性:
- 同一窗口只能二选一,不能同时开启
- 半透明只能完全半透明,子窗口无法取消,无法局部不透明。
- 镂空透过指定关键颜色,扣除法实现,镂空部分可以点击到窗体后面
为什么部分镂空需要无边框
- 发现普通窗口镂空存在BUG,当子窗口部分镂空时(WM_PAINT绘制透明关键色),则父窗口在子窗口底部下方区域50像素左右的高度失去点击事件的响应。猜测是将此部分区域当作caption标题栏处理了。
镂空部分下方区域,窗口失去焦点,失去响应。
抬高绘制区域50像素,则又可以响应。
screenshots.gif这个应该不是duilib的问题。测试时已经注释掉相关代码(WM_NCHITTEST)。
无边框窗口如何实现窗口缩放?
duilib 通过指定window sizebox属性在窗体四边指定区域,响应 WM_NCHITTEST 事件,判断鼠标位置,在四个边上返回 HTTOPLEFT 等系统预设值,代表四个边或四个角,与普通窗口差不多。
但此时又出现坑点了。这也是为什么我不推荐无边框窗体的原因之一,问题太多。
问题就是 sizebox 属性只适合单窗口,如果duilib主窗口嵌套其他duilib窗口、嵌套其他控件窗口如播放器窗口、浏览器窗口等,则四边区域无法响应 WM_NCHITTEST 事件,完全收不到,主消息循环也拦截不到,除非四边空出一段距离。子窗口倒是可以接收与响应 WM_NCHITTEST 事件,然而一旦响应,则变成子窗口在父窗口内部的缩放改变大小。
所以需要其他方案,参考csdn收藏的一篇:Win32无边框窗体拖动、改变大小(WM_SYSCOMMAND方式),记录较为详细。可以在鼠标点击某些区域的时候,发送系统消息,触发窗口移动及缩放。
无边框窗口为何没有最大化、最小化动画
像百度网盘这种窗口,最大化、最小化没有动画,右上角按钮极小,属于负面教材。
无边框窗口之所以在最大化、最小化的时候没有动画,可能是窗口样式扣除了 WS_CAPTION 导致的。见以下代码,如果在窗口建立之前扣除没事,建立之后再抠出就会失去动画。
HWND CWindowWnd::Create(HWND hwndParent, LPCTSTR pstrName, DWORD dwStyle, DWORD dwExStyle, int x, int y, int cx, int cy, bool center, HMENU hMenu)
{
// 调整窗口样式
WindowImplBase* _this = dynamic_cast<WindowImplBase*>(this);
if (_this)
{
if(_this->IsWindowLess()) dwStyle &= ~WS_CAPTION;
else _this = NULL;
dwStyle |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
}
if( GetSuperClassName() != NULL && !RegisterSuperclass() ) return NULL;
if( GetSuperClassName() == NULL && !RegisterWindowClass() ) return NULL;
LPWSTR lpClassName = (LPWSTR)GetWindowClassName();
LPWSTR lpName = (LPWSTR)pstrName;
m_hWnd = ::CreateWindowEx(dwExStyle, lpClassName, lpName, dwStyle, x, y, cx, cy, hwndParent, hMenu, CPaintManagerUI::GetInstance(), this);
if (_this)
{
//LONG styleValue = ::GetWindowLong(*this, GWL_STYLE);
//::SetWindowLong(*this, GWL_STYLE, styleValue & ~WS_CAPTION);
}
无边框窗口如何模拟系统标题栏
像chrome这种是如何绘制三个按钮的呢,代码卷帙浩繁难以取经,不如自制,应该不难。
百度网盘这种自己瞎画的,还请大家不要随便模仿。
potplayer 也是无边框,但是竟然没有菜单栏,而是用层级超多的右键菜单,而且鼠标稍微一移动就消失了,用起来气人。
模拟菜单栏
顶部自绘模拟的菜单栏可以布局在标题栏内部,不单独占用屏幕空间。
网友评论