admin管理员组文章数量:1652896
背景
最近在学习duilib这个库,看了网上Alberl的教程,他那个仿迅雷播放器做的不错,我就直接拿来学习duilib了。不过这个播放器有个缺点,就是无法双击全屏,也就是鼠标放到libVLC播放窗口时无法响应消息,消息都被libVLC内部处理了。这对我们而言不是很方便。因为有时我们需要双击全屏,或者弹出鼠标右键菜单做一些操作。后来上网查了下,好多人遇到这个问题。下面是一些查到的解决方法。
解决libVLC无法响应鼠标消息
如下是查到的一些方法:
1)使用全局钩子;
2)修改libVLC鼠标消息处理代码,重新编译;
3)禁用子窗口消息。
第一种方法不安全,容易被杀毒软件干掉,而且效率不高,第二种方法麻烦,编译就得花你好多时间,而且很麻烦,第三种方法比较简单,解决方法如下:
// 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
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
BOOLCALLBACKEnumerateVLC(HWNDhWndvlc,LPARAMlParam){
EnableWindow(hWndvlc,FALSE);
// And kill timer, i only need get this handle one time.
returnTRUE;
}
// When EnumerateVLC is called all mouse events are redirected to MyWindow
具体实现见下面。
基于duilib实现
duilib学起来还是很容易上手的,这里我的代码是基于Alberl的仿迅雷播放器。最后实现的界面如下:
按照上面的解决方法,在这个程序中我是这么解决无法响应消息的:
1)当开始播放某个文件后,创建一个一秒的定时器(也可以不创建,直接跳到直接第二步,创建定时器是为了确保我们处理时VLC窗口已经生成);
SetTimer(NULL, 1, 1000, TimeProc);
1
SetTimer(NULL,1,1000,TimeProc);
2)在定时器的回调函数中枚举得到VLC创建的窗口的句柄,通过spy++可以了解到libVLC创建的播放窗口名为:VLC video output,获取到VLC窗口的句柄后使用EnableWindow函数禁用掉键鼠输入,EnableWindow函数的作用是允许/禁止指定的窗口或控件接受鼠标和键盘的输入,代码如下:
C++
//定时器回调
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;
}
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
//定时器回调
voidCALLBACKTimeProc(
HWNDhwnd,
UINTmessage,
UINTidTimer,
DWORDdwTime)
{
//我的播放器窗口名称为JCHPlayer,也可以直接获取主程序窗口句柄
WCHAR*strWindwoName=L"JCHPlayer";
HWNDhNMMainWnd=FindWindowEx(NULL,NULL,NULL,strWindwoName);
if(hNMMainWnd!=NULL)
{
EnumChildWindows(hNMMainWnd,EnumerateVLC,NULL);
}
}
//枚举得到VLC播放窗口句柄
BOOLCALLBACKEnumerateVLC(HWNDhWndvlc,LPARAMlParam)
{
TCHARszWndTitle[1024];
intnLen=GetWindowText(hWndvlc,szWndTitle,1024);
if(0!=nLen)
{
//禁用鼠标消息
EnableWindow(hWndvlc,FALSE);
KillTimer(NULL,1);
}
returnTRUE;
}
通过如上方法,在VLC播放窗口上的鼠标键盘消息我们都可以获得,这样就可以去实现自己想要的功能。比如我在全屏时响应WM_MOUSEMOVE消息,实现底部播放面板自动隐藏。双击全屏也很简单,当响应双击消息时,只显示作为libvlc父窗口那个控件,其他控件都隐藏即可。整个播放器的代码我已经上传到Github。
地址:https://github/yjfxfjch/JCHPlayer
我是用的是VS2015编译,低版本VS可能无法直接打开编译。下面一节是使用MFC做界面实现的版本。
基于MFC实现
1)在MFC对话框程序中,首先添加一个控件,这里我添加了一个Picture Contron:IDC_PLAYWND;
2)获得IDC_PLAYWND控件句柄;
C++
gPlayHwnd = GetDlgItem(IDC_PLAYWND)->GetSafeHwnd();
1
gPlayHwnd=GetDlgItem(IDC_PLAYWND)->GetSafeHwnd();
3)让libVLC播放对象设置gPlayHwnd 为播放窗口句柄,这样libVLC播放窗口就成为IDC_PLAYWND控件的子窗口;
libvlc_media_player_set_hwnd (mp, gPlayHwnd );
1
libvlc_media_player_set_hwnd(mp,gPlayHwnd);
4)开始播放后创建一个定时器(也可以不创建,直接EnableWindow相应窗口句柄);
C++
::SetTimer(NULL, 1, 1000, TimeProc);
1
::SetTimer(NULL,1,1000,TimeProc);
5)定时器回调函数以及处理过程如下:
C++
//定时器回调
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;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//定时器回调
voidCALLBACKTimeProc(
HWNDhwnd,
UINTmessage,
UINTidTimer,
DWORDdwTime)
{
EnumChildWindows(gPlayHwnd,EnumerateVLC,NULL);
}
BOOLCALLBACKEnumerateVLC(HWNDhWndvlc,LPARAMlParam)
{
TCHARszWndTitle[1024];
intnLen=GetWindowText(hWndvlc,szWndTitle,1024);
if(0!=nLen)
{
//禁用鼠标消息
EnableWindow(hWndvlc,FALSE);
KillTimer(NULL,1);
}
returnTRUE;
}
在上述代码中,我们通过之前得到的IDC_PLAYWND控件句柄枚举得到子窗口VLC播放窗口句柄,接着通过EnableWindow函数禁止VLC播放窗口接受鼠标键盘输入。这时我们的程序就可以响应鼠标点击libVLC播放窗口的消息了;
6)设置全屏,主要是设置IDC_PLAYWND控件全屏时占满整个屏幕,然后隐藏其他控件以及标题栏,这样VLC子窗口就可以全屏播放了。不需要使用libvlc_set_fullscreen这个内置api,使用这个api无法达到效果。
最后实现的简单版本如下:
MFC版本支持双击全屏的libvlc播放器代码我也上传到Github,具体的可以去看下。
Github地址:https://github/yjfxfjch/SimpleVlcPlayer
版权声明:本文标题:paslibvlc使用方法_使用libVLC实现的播放器:支持双击全屏 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://www.elefans.com/xitong/1729620070a1208130.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论