JCHub

  • Home
  • Category
    • A/V
    • WebRTC
    • Beauty of Programming
    • Linux
    • Windows
    • Moments of Life
    • Campus Life
  • Reference
    • API Reference
    • Utilities
    • AV Test
    • Doc
  • Message Board
  • About
JCHub
Code as My Sword, Lost in Obsession
  1. Main page
  2. A/V
  3. Main content

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

2015年11月23日 11076hotness 12likes 15comments

背景

最近在学习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

This article is licensed with Creative Commons Attribution-NonCommercial-No Derivatives 4.0 International License
Tag: VC++ 音视频
Last updated:2022年3月27日

Jeff

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

Tip the author Like
< Last article
Next article >

Comments

  • zhao

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

    2016年4月21日
    Reply
    • Jianchihu

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

      2016年4月22日
      Reply
  • liwei

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

    2017年11月20日
    Reply
    • Jianchihu

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

      2017年11月23日
      Reply
  • Jerry

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

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

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

    2018年4月11日
    Reply
    • Jianchihu

      @Jerry

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

      2018年4月11日
      Reply
  • Jerry

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

    2018年4月12日
    Reply
    • Jianchihu

      @Jerry

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

       

      2018年5月17日
      Reply
  • sean

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

    2018年7月12日
    Reply
    • Jianchihu

      @sean

       

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

       

      2018年7月18日
      Reply
  • 菲儿

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

    谢谢楼主。

    2018年8月6日
    Reply
    • Jianchihu

      @菲儿

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

       

      2018年8月6日
      Reply
  • startline

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

    2020年10月18日
    Reply
  • jy

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

    2020年10月23日
    Reply
    • Jeff

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

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

    This site uses Akismet to reduce spam. Learn how your comment data is processed.

    文章目录
    • 背景
    • 解决libVLC无法响应鼠标消息
    • 基于duilib实现
    • 基于MFC实现
    Related Posts
    • 基于FireBreath的npapi插件在Firefox下的调试
    • 告别CapCut收费!开源视频剪辑工具OpenCut 来了
    • 音视频开发入门:视频基础
    • 大话WebRTC
    • WebRTC音视频传输基础:NAT穿透
    Categories

    COPYRIGHT © 2026 jianchihu.net. ALL RIGHTS RESERVED.

    Theme Kratos Made By Seaton Jiang