处理LibVLCSharp.WPF鼠标点击事件

因为我以前没用过VLC控件,但是最近有小伙伴问到我这个问题。

说是使用了LibVLCSharp.WPF里面的视频播放控件,无法处理鼠标点击事件。

其实这种一般原因也比较明确,就是LibVLCSharp.WPF里面的视频播放器是一个Win32的控件,直接通过WPF的事件处理机制,是无法捕获到鼠标点击 事件的。

除非这个控件自己抛出了事件,否则无法直接处理。

在我前面的一篇文章《WPF创建不规则窗体时WebBrowser控件不显示的问题》里我大概介绍过这个问题,主要是由于空域问题导致。

我在网上搜了一圈,发现解决方法比较少。这里分享一下解决方案,给有需要的小伙伴。

这里提供两种解决方案。

一、添加一个事件处理面板

因为我们点击事件被VideoView把事件“吞了”

在WPF里,会有事件路由机制,但是Win32里没有,所以这个事件就是直接被吞了

仔细观察发现,VideoView是一个内容控件,但是运行后,发现VideoView.Content是为空的,说明VideoView只是一个宿主控件而已。内部会进行重绘(猜想,未经证实)。

此时我们只需要设置一下VideoView.Content为一个面板,并设置透明度为几乎透明的状态,这样,我们能看到视频播放效果,也能对事件进行处理。

 1  <Grid>
 2      <vlc:VideoView x:Name="videoView">    
 3          <Grid MouseLeftButtonDown="videoView_MouseDown">
 4              <Grid.Background>
 5                  <SolidColorBrush Color="White" Opacity="0.01"></SolidColorBrush>
 6              </Grid.Background>
 7          </Grid>
 8      </vlc:VideoView>
 9     
10  </Grid>

事件处理函数如下

1  private void videoView_MouseDown(object sender, MouseButtonEventArgs e)
2  {
3      if(e.ClickCount == 2)
4      {
5          MessageBox.Show("双击");
6      }
7  }

这样我们就能对鼠标点击事件进行处理

注意:双击和单击的处理需要通过两次点击时间间隔去判断,而不能通过e.ClickCount,这里就不做详细介绍了

二、使用钩子函数

我们使用Spyxx对控件的窗口句柄进行查看

然后将这个值跟LibVLCSharp.Shared.MediaPlayer.Hwnd进行对比,发现是一样的。

我们可以借助SetWinodwsHookEx函数,来获取这个句柄的Win32消息。

但是初次尝试,发现创建钩子不成功,后面又尝试了一下,使用子窗口Direct3D11 output这个窗口是可以的。

实现步骤如下:

1、导入Winapi函数

 1 [DllImport("user32.dll", SetLastError = true)]
 2 private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);
 3 
 4 [DllImport("user32.dll", SetLastError = true)]
 5 [return: MarshalAs(UnmanagedType.Bool)]
 6 private static extern bool UnhookWindowsHookEx(IntPtr hhk);
 7 
 8 [DllImport("user32.dll")]
 9 private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
10 
11 [DllImport("user32.dll")]
12 private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId);
13 
14 private const int WH_MOUSE = 7;
15 private const int WH_MOUSE_LL = 14;
16 private const int WM_LBUTTONDOWN = 0x0201;
17 private const int WM_RBUTTONDOWN = 0x0204;
18 private const int WM_LBUTTONDBLCLK = 0x0203;
19 
20 private static IntPtr hookID = IntPtr.Zero;
21 private static LowLevelMouseProc mouseProc = HookCallback;
22 
23 private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);
24 
25 [DllImport("user32.dll")]
26 private static extern bool EnumChildWindows(IntPtr hWndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam);
27 
28 private delegate bool EnumWindowsProc(IntPtr hwnd, IntPtr lParam);
29 
30 public static List<IntPtr> GetAllChildHandles(IntPtr parentHwnd)
31 {
32     List<IntPtr> result = new List<IntPtr>();
33     EnumChildWindows(parentHwnd, (hWnd, lParam) =>
34     {
35         result.Add(hWnd);
36         return true;
37     }, IntPtr.Zero);
38     return result;
39 }

2、在窗口加载事件里创建钩子

 1  public async void SetHook(IntPtr hwnd)
 2  {
 3      //等待,防止运行较慢,窗口未显示
 4      await Task.Delay(1000);
 5 
 6      var childWindowList = GetAllChildHandles(hwnd);
 7 
 8      if(childWindowList == null || childWindowList.Count == 0)
 9      {
10          return;
11      }
12 
13      hookID = SetWindowsHookEx(WH_MOUSE, mouseProc, IntPtr.Zero, GetWindowThreadProcessId(childWindowList[0], out _));
14  }

3、钩子处理函数

 1  private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
 2  {
 3      if (nCode >= 0)
 4      {
 5          if((int)wParam == WM_LBUTTONDBLCLK)
 6          {
 7              MessageBox.Show("双击");
 8          }
 9      }
10      return CallNextHookEx(hookID, nCode, wParam, lParam);
11  }

4、在主窗口关闭时,卸载钩子

1  private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
2  {
3      Unhook();
4  }

运行效果如下:

示例代码

下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

△曉風殘月〆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值