剑痴乎

  • 首页
  • 文章分类
    • 音视频
    • WebRTC
    • 编程之美
    • Linux
    • Windows
    • 生活点滴
    • 校园生活
  • 参考
    • API参考
    • 实用工具
    • 测试音视频
    • 文档
  • 留言板
  • 关于
剑痴乎
代码为剑,如痴如醉
  1. 首页
  2. Windows
  3. 正文

使用libVLC实现的播放器:支持双击全屏

2015年11月23日 9514点热度 12人点赞 15条评论

背景

最近在学习duilib这个库,看了网上Alberl的教程,他那个仿迅雷播放器做的不错,我就直接拿来学习duilib了。不过这个播放器有个缺点,就是无法双击全屏,也就是鼠标放到libVLC播放窗口时无法响应消息,消息都被libVLC内部处理了。这对我们而言不是很方便。因为有时我们需要双击全屏,或者弹出鼠标右键菜单做一些操作。后来上网查了下,好多人遇到这个问题。下面是一些查到的解决方法。

解决libVLC无法响应鼠标消息

如下是查到的一些方法:
1)使用全局钩子;
2)修改libVLC鼠标消息处理代码,重新编译;
3)禁用子窗口消息。
第一种方法不安全,容易被杀毒软件干掉,而且效率不高,第二种方法麻烦,编译就得花你好多时间,而且很麻烦,第三种方法比较简单,解决方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
// First step is start a timer when you play a video,
 
// Second step : in the timer function i call :
EnumChildWindows(MyWindow_HWND, EnumerateVLC, NULL);
 
// Third step : if EnumerateVlc get some child window these window is the VlcEventWindow, and need disable it, to reach mouse events on MyWindow
BOOL CALLBACK EnumerateVLC(HWND hWndvlc, LPARAM lParam) {
   EnableWindow(hWndvlc, FALSE);
   // And kill timer, i only need get this handle one time.
   return TRUE;
}
 
// When EnumerateVLC is called all mouse events are redirected to MyWindow

具体实现见下面。

基于duilib实现

duilib学起来还是很容易上手的,这里我的代码是基于Alberl的仿迅雷播放器。最后实现的界面如下:

按照上面的解决方法,在这个程序中我是这么解决无法响应消息的:
1)当开始播放某个文件后,创建一个一秒的定时器(也可以不创建,直接跳到直接第二步,创建定时器是为了确保我们处理时VLC窗口已经生成);

1
SetTimer(NULL, 1, 1000, TimeProc);

2)在定时器的回调函数中枚举得到VLC创建的窗口的句柄,通过spy++可以了解到libVLC创建的播放窗口名为:VLC video output,获取到VLC窗口的句柄后使用EnableWindow函数禁用掉键鼠输入,EnableWindow函数的作用是允许/禁止指定的窗口或控件接受鼠标和键盘的输入,代码如下:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//定时器回调
void CALLBACK TimeProc(
HWND hwnd,
UINT message,
UINT idTimer,
DWORD dwTime)
{
//我的播放器窗口名称为JCHPlayer,也可以直接获取主程序窗口句柄
WCHAR *strWindwoName = L"JCHPlayer";
HWND hNMMainWnd = FindWindowEx(NULL, NULL, NULL, strWindwoName);
if (hNMMainWnd != NULL)
{
EnumChildWindows(hNMMainWnd, EnumerateVLC, NULL);
}
}
 
//枚举得到VLC播放窗口句柄
BOOL CALLBACK EnumerateVLC(HWND hWndvlc, LPARAM lParam)
{
TCHAR szWndTitle[1024];
int nLen = GetWindowText(hWndvlc, szWndTitle, 1024);
if (0!= nLen)
{
//禁用鼠标消息
EnableWindow(hWndvlc, FALSE);
        KillTimer(NULL, 1);
}
 
return TRUE;
}

通过如上方法,在VLC播放窗口上的鼠标键盘消息我们都可以获得,这样就可以去实现自己想要的功能。比如我在全屏时响应WM_MOUSEMOVE消息,实现底部播放面板自动隐藏。双击全屏也很简单,当响应双击消息时,只显示作为libvlc父窗口那个控件,其他控件都隐藏即可。整个播放器的代码我已经上传到Github。
地址:https://github.com/yjfxfjch/JCHPlayer
我是用的是VS2015编译,低版本VS可能无法直接打开编译。下面一节是使用MFC做界面实现的版本。

基于MFC实现

1)在MFC对话框程序中,首先添加一个控件,这里我添加了一个Picture Contron:IDC_PLAYWND;
2)获得IDC_PLAYWND控件句柄;

C++
1
gPlayHwnd = GetDlgItem(IDC_PLAYWND)->GetSafeHwnd();

3)让libVLC播放对象设置gPlayHwnd 为播放窗口句柄,这样libVLC播放窗口就成为IDC_PLAYWND控件的子窗口;

1
libvlc_media_player_set_hwnd (mp, gPlayHwnd );

4)开始播放后创建一个定时器(也可以不创建,直接EnableWindow相应窗口句柄);

C++
1
::SetTimer(NULL, 1, 1000, TimeProc);

5)定时器回调函数以及处理过程如下:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//定时器回调
void CALLBACK TimeProc(
HWND hwnd,
UINT message,
UINT idTimer,
DWORD dwTime)
{
EnumChildWindows(gPlayHwnd, EnumerateVLC, NULL);
}
 
BOOL CALLBACK EnumerateVLC(HWND hWndvlc, LPARAM lParam)
{
TCHAR szWndTitle[1024];
int nLen = GetWindowText(hWndvlc, szWndTitle, 1024);
if (0 != nLen)
{
//禁用鼠标消息
EnableWindow(hWndvlc, FALSE);
        KillTimer(NULL, 1);
}
return TRUE;
}

在上述代码中,我们通过之前得到的IDC_PLAYWND控件句柄枚举得到子窗口VLC播放窗口句柄,接着通过EnableWindow函数禁止VLC播放窗口接受鼠标键盘输入。这时我们的程序就可以响应鼠标点击libVLC播放窗口的消息了;
6)设置全屏,主要是设置IDC_PLAYWND控件全屏时占满整个屏幕,然后隐藏其他控件以及标题栏,这样VLC子窗口就可以全屏播放了。不需要使用libvlc_set_fullscreen这个内置api,使用这个api无法达到效果。
最后实现的简单版本如下:
支持全屏的libvlc mfc播放器

MFC版本支持双击全屏的libvlc播放器代码我也上传到Github,具体的可以去看下。
Github地址:https://github.com/yjfxfjch/SimpleVlcPlayer

本作品采用 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议 进行许可
标签: VC++ 音视频
最后更新:2022年3月27日

Jeff

管理员——代码为剑,如痴如醉

打赏 点赞
< 上一篇
下一篇 >

文章评论

  • zhao

    博主好厉害啊。。我最近也在研究VLC,可以加个好友吗,我的QQ770552117

    2016年4月21日
    回复
    • Jianchihu

      @zhao 有什么问题可以发邮件问我,我现在很少用QQ的。

      2016年4月22日
      回复
  • liwei

    博主你好。我这使用vlc的webplugin做网页版的播放器,其中就需要js去获取鼠标点击事件。请问博主这个方法是否可以使用于html上。或者博主是否知道什么更好的方法。谢谢指教

    2017年11月20日
    回复
    • Jianchihu

      @liwei 我这个是通过系统api实现的,js肯定没那么大权限,只能通过修改你vlc插件源代码了。现在web都不提倡用这种NPAPI插件或activex控件了,浏览器也都默认禁用。最好的方法是用js写一个,现在html5功能也够强大。你可以参考下flv.js,修改下,基本上各种协议都能实现播放。

      2017年11月23日
      回复
  • Jerry

    hi,哥们,我从 https://github.com/yjfxfjch/JCHPlayer 这里下载,

    然后更新了下Duilib(https://github.com/qdtroy/DuiLib_Ultimate)库,

    发现播放时播放区域总是黑色,但是有进度在前进,请问下,这个可能是因为什么导致的? 

    2018年4月11日
    回复
    • Jianchihu

      @Jerry

      我有空看下,好久的代码了,到时给你回复

      2018年4月11日
      回复
  • Jerry

    调试发现,class CWndUI: public CControlUI 中的setpos不会被调用,然后对比了您的duilib库,发现改动有点大,感觉应该是在消息回调这边可能您有做了些特殊处理,但是代码量有点,所以只能麻烦博主了

    2018年4月12日
    回复
    • Jianchihu

      @Jerry

      现在太忙了,没时间看这些了,靠你自己了,我已经不搞界面这一套了,当时我的界面库都是官方下的,没改动过

       

      2018年5月17日
      回复
  • sean

    博主你好。请问怎么调用音频的频谱?那个接口一直找不到

    2018年7月12日
    回复
    • Jianchihu

      @sean

       

      抱歉,我找了下也没找到,这个要自己写代码计算了,反正就那几个数学变换

       

      2018年7月18日
      回复
  • 菲儿

    CDuiFrameDlg *pFrame = new CDuiFrameDlg(_T("Player.xml"));  Player.xml哪里可以下载到?

    谢谢楼主。

    2018年8月6日
    回复
    • Jianchihu

      @菲儿

      https://github.com/yjfxfjch/JCHPlayer/tree/master/Release/skin

       

      2018年8月6日
      回复
  • startline

    其实,最简单的就是把libvlc_media_player_set_hwnd的那个窗口设成禁用就可以了

    2020年10月18日
    回复
  • jy

    求助...............使用网易nim_duilib时,创建的子窗口无法显示视频,报错core vout display error: Failed to set on top

    2020年10月23日
    回复
    • Jeff

      @jy sorry,已经不搞windows客户端开发了

      2020年10月24日
      回复
  • razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
    取消回复

    这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理。

    文章目录
    • 背景
    • 解决libVLC无法响应鼠标消息
    • 基于duilib实现
    • 基于MFC实现
    相关文章
    • 基于FireBreath的npapi插件在Firefox下的调试
    • 音视频开发入门:视频基础
    • 大话WebRTC
    • WebRTC音视频传输基础:NAT穿透
    • Intel平台硬件加速视频编解码开发

    COPYRIGHT © 2025 jianchihu.net. ALL RIGHTS RESERVED.

    Theme Kratos Made By Seaton Jiang